Jest/RTL Test Component Not Unmounting - Or is it? Can't perform a React state update on an unmounted component

Viewed 31

I'm using React, Redux, Redux-Saga, and Jest with React Testing Library.

I'm writing tests for a component based on the Guiding Principles listed on the Redux site.

I have test utilities set up with a reusable test render function also as noted in the Redux docs with the notable exception that, due to current limitations in the codebase, I can not re-create a new store between each test.

Instead, between each test, I just reset the state via reducers.

I have two issues:

  1. I don't see the useEffect unmount called during my test
  2. Redux store is trying to update an unmounted component

My component (simplified for repro) looks like this:

export function SearchResultDisplayer(): JSX.Element {
  const searchState = useSelector(data.search.getSearchState);
  const onSearchRequest = data.interactions.search.setSearchResults;

  React.useEffect(() => {
    console.log('SRD Effect');

    return () => {
      console.log('SRD Unmount');
    };
  }, []);

  function handleClick() {
    onSearchRequest({});
  }

  return (
    <>
      <div>{Object.values(searchState.results).map((result) => result.id)}</div>
      <button
        type="button"
        onClick={handleClick}
      >
        Click Me!
      </button>
    </>
  );
}

My tests look like this:

  test('test 1', () => {
    const { unmount } = render(<SearchResultDisplayer />);

    unmount();
    cleanup();
  });

  test('test 2', async () => {
    const { getByRole } = render(<SearchResultDisplayer />);

    const button = await getByRole('button');

    await fireEvent.click(button);
  });

I expect to see, during the first test, the console.log('SRD Unmount') - but this doesn't seem to be called (it is called when I test in the browser).

Additionally, during the second test, when I await fireEvent.click(button) I receive the react error:

Warning: Can't perform a React state update on an unmounted component...

which seems to be related to the Redux store trying to update the component from the first test - the error does not show up if I only run the 2nd test. Additionally, this happens regardless of whether the useEffect is present or not - I only added that to try to confirm the component was getting unmounted.

So from the first test, the component is obviously unmounted, given the error - but...

  • why don't I see the console log during unmount?
  • why is the Redux Store still trying to perform a state update on that component? (and how can I prevent that in the test?)
0 Answers
Related