How to Unit Test a Custom React Hooks ⚓

HK01 Product & Technology team
HK01 Tech Blog
Published in
4 min readJun 11, 2019

--

By Ivan Ha, Senior Software Engineer

React Hooks is released in React 16.8 and gaining massive attention. It’s a completely opt-in solution aimed to solve many problems in React, e.g. reuse stateful logic between components, avoid unrelated logic spreading across different lifecycle methods.

To understand more about React Hooks, check out below video and the official documentation.

In HK01, we’ve been using React Hooks for a while and implemented a bunch of custom Hooks for our needs. In this article, we will demonstrate building a simple custom React Hooks to fetch data from an API and how we could unit test it.

If you’re familiar with how to build a custom React Hooks, and just want to know how to unit test it, just scroll to “Unit Testing the Custom React Hooks”.

The code of the article can be found at https://github.com/ivan-ha/react-hooks-test

As a React developer, regardless of what product you’re building, you probably come across with to implement a list view to show data fetched from an external API. So in this article let’s use this as our imaginal requirement. And to simplify the demo, we’ll use the API from https://randomuser.me/

The Traditional Way

If you have some experience in React, in order to fulfill the requirement, you’ll likely use a class component, then fetch data in componentDidMount(), and store the response to state or any state management library like Redux and MobX.

We’ve implemented a list view showing some users’ name from an API.

Using React Hooks

The above class component perfectly performs what we expected. But we’re cool kids, let’s re-implement it using React Hooks!

Making an external API call is a kind of side effect, so we should use the useEffect() Hook. And to use state in a functional component, we will use the useState() Hook also.

Perfect, our App is still working like before.

Extracting to a Custom Hook

We’ve successfully re-implement our App with Hooks. Now, let’s imagine in our App, there are multiple components need to fetch the same API, we definitely don’t want to copy and paste over and over. It’s time to extract a custom React Hook so that others could reuse it.

It’s just like extracting that chunk of code into another file, and invoke it in our component, easy!

Unit Testing the Custom React Hooks

In HK01, we embrace the benefits of unit testing, and without exception, we of course will unit test our custom Hook as well.

The custom React Hooks just look similar to a function, so we might intuitively think we can mock the API response, and assert the return value of the Hook. Like below:

It looks perfect, right? However, React gives us a big error message!

Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component.

Exactly as the message implies, Hooks can only be run inside a functional component.

Therefore, in order to unit test our React Hooks, we need to wrap it with a dummy functional component, just like what mentioned in other articles.

However, it would be quite clumsy if we need to do that in every unit test, or we could definitely extract some sort of testing helpers and reuse it. Fortunately, someone did that already! react-hooks-testing-library is exactly what we want.

Let’s re-write our test with react-hooks-testing-library.

Nice! The unit test passed. But wait… there is a warning in our test ⚠️, saying we need to wrap the state updates with act().

We’re not going explain what is act() and why it’s needed, otherwise, this article will be way too long 😄. But if you’re interested, react-act-examples is something you cannot miss.

If you want to eliminate the warning, you will first need to bump react, react-dom, react-test-renderer to 16.9.0-alpha.0 since our usage is still unsupported in current React. Then you need to wrap the waitForNextUpdate() with act() like so:

// before
await waitForNextUpdate();
// after
await act(() => waitForNextUpdate());

However, if it’s a critical product, you probably don’t want to use an alpha release of any library, we suggest you to just live with it at the moment until React 16.9 is officially launched.

In this article, we’ve go through how to rewrite traditional class component with custom React Hooks. And how we could easily unit test it with react-hooks-testing-library.

The code of the article can be found at https://github.com/ivan-ha/react-hooks-test

Thanks for reading, clap 👏 if you like it. We are hiring, job descriptions can be found HERE.

Originally published at https://medium.com on June 11, 2019.

--

--