Building & Testing React Hooks with NPM
Martin Persson
Posted on September 12, 2023
Table of Contents
Introduction
This tutorial aims to guide you through setting up an NPM package specifically designed for React projects. You'll learn how to create and test a custom hook as well.
Links:
What you will learn:
- NPM Package Setup: Steps to create an NPM package for React projects or custom component libraries.
- Custom Form Hook Creation: How to build a simple but extensible custom hook.
- Testing in React: Utilize Jest and React Testing Library to test React components and hooks.
This tutorial builds upon a previous guide where we created a basic NPM package. If you haven't checked that out yet, you might want to start there.
Setting up the project
Firstly, ensure you have Node and npm installed. To kickstart your project, clone the starter code from the GitHub repository:
git clone https://github.com/Mumma6/npm-package-tutorial
Navigate into the project directory:
cd npm-package-tutorial/
After you've cloned the starter code, you'll want to set up your own GitHub repository. Here is how to do that:
-
Create a New Repository on GitHub:
- Go to your GitHub account and create a new repository.
- Do not initialize the new repository with a README,
.gitignore
, or license. This empty repository will be linked to your local project.
-
Change the Remote URL:
- Open your terminal and navigate to your local project directory.
- Type
git remote -v
to list the current configured remote repository for your fork. - Run
git remote set-url origin YOUR-NEW-REPOSITORY-URL.git
to change the repository URL to your newly created repository.
-
Verify the Remote URL:
- Again, run
git remote -v
to verify that the remote URL has been updated.
- Again, run
-
Push to New Repository:
- Run
git push -u origin main
(orgit push -u origin master
depending on your default branch name) to push your local code to your own GitHub repository.
- Run
After these steps, your local repository will be linked to your new GitHub repository, and you can start making commits and pushing changes.
Note: If you plan to publish this package, make sure to change the name in your
package.json
to avoid conflicts with existing packages.
Install Dependencies
Install React and React DOM. We'll use version 17 to maintain compatibility with React Testing Library:
npm i react@17 react-dom@17 @types/react@17 @types/react-dom@17
Rollup Configuration
Update your Rollup configuration to include React and React DOM as external dependencies:
const typescript = require("rollup-plugin-typescript2")
const pkg = require("./package.json")
module.exports = {
input: 'src/index.ts',
output: [
{
file: pkg.main,
format: 'cjs',
exports: 'named',
sourcemap: true,
strict: false
}
],
plugins: [
typescript()
],
external: ['react', 'react-dom']
}
Create our hook
Let's create our custom form hook. For simplicity, the hook will be minimal:
In you index.ts file create this.
import { useState } from "react"
export function useForm(formData: any) {
const [values, setValues] = useState(formData)
return {
values,
setValues,
}
}
Testing
For testing we are going to use Jest and React Testing Library.
Jest
Jest is a popular testing framework in the JavaScript ecosystem that comes with a lot of features out-of-the-box, like mocking, assertions, and snapshot testing. It's widely used in the React community, partly because create-react-app includes it by default.
React Testing Library
React Testing Library is built on top of Jest and provides a set of utilities to test React components. It encourages better testing practices and makes it easier to find elements and interact with them in a way that resembles how the end-user would.
Testing Hooks with @testing-library/react-hooks
While React Testing Library primarily focuses on React components, @testing-library/react-hooks is an extension that allows us to test React hooks in isolation from the components that use them. This is particularly useful for your tutorial since you're building a hook.
The renderHook and act Functions
In our test example, we use two primary functions: renderHook and act.
- renderHook: This function "renders" your hook in a testing environment, much like render does for components. It returns an object that contains the hook's return value, among other things.
- act: When you need to interact with your hook (for example, to change a state variable), wrap those interactions in an act function to ensure that all updates related to these actions have been processed and applied to the DOM before you make any assertions.
To test our hook, install the required testing libraries:
npm i @testing-library/react-hooks @testing-library/jest-dom jest-environment-jsdom
Create a file called setupTests.ts and add the following line:
import "@testing-library/jest-dom"
Update your Jest configuration to include the new environment and setup file:
module.exports = {
preset: 'ts-jest',
testMatch: ["**/__tests__/**/*.test.ts"],
testEnvironment: 'jest-environment-jsdom',
setupFilesAfterEnv: ['./setupTests.ts'],
};
Now, create a folder called __tests__
and add a test file index.test.ts
with the following content:
import { renderHook, act } from "@testing-library/react-hooks"
import { useForm } from "../src/index"
describe("useFormHook", () => {
test("should update form values", () => {
const { result } = renderHook(() => useForm({ name: "", email: "" }))
act(() => {
result.current.setValues({ name: "John", email: "john@example.com" })
})
expect(result.current.values).toEqual({ name: "John", email: "john@example.com" })
})
})
You can now run the test with npm test
Conclusion
Congratulations on making it to the end of this tutorial! You've successfully built an NPM package tailored for React projects, complete with a custom hook. Not only did you develop the hook, but you also ensured its robustness by writing tests using Jest and React Testing Library. This not only amplifies the quality of your package but also provides peace of mind when integrating it into larger, more complex systems.
What's more, your package is now ready for publishing on NPM, opening up the possibility for other developers to make use of your work in their projects. If you're unsure about how to publish your package, you can refer back to my previous guide for a detailed walk-through on publishing it to NPM.
As a next step, you might consider adding more features to your custom hook, or perhaps even expand it into a full-fledged React component library. The possibilities are endless, and the foundations laid in this tutorial will serve you well as you continue on your journey in React development.
Posted on September 12, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.