testing-library/react-hooks-testing-library

renderHook doesn't work with the custom hook that has useMemo

mzbac opened this issue · 2 comments

mzbac commented
  • react-hooks-testing-library version: 7.0.2
  • react version: 17.0.2
  • react-dom version (if applicable): 17.0.2
  • react-test-renderer version (if applicable):
  • node version: 16
  • npm (or yarn) version: 8.5.0

Relevant code or config:

// custom hook
import {useMemo, useState} from 'react';

export const useRenderHookWithMemo = (nums: number[]) => {
  const [isGreater, setIsGreater] = useState(false);

  const numsGreaterThanFive = useMemo(() => {
    const result: number[] = [];

    for (const num of nums) {
      if (num > 5) {
        setIsGreater(true);
        result.push(num);
      }
    }

    return result;
  }, [nums]);

  return [isGreater, numsGreaterThanFive] as const;
};

// test
import {renderHook} from '@testing-library/react-hooks';

import {useRenderHookWithMemo} from './renderhook';

test('useRenderHookWithMemo', () => {
  const {result} = renderHook(() =>
    useRenderHookWithMemo([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]),
  );

  const [isGreater, nums] = result.current;

  expect(isGreater).toBeTruthy();
  expect(nums.length).toBe(5);
});

What you did:

when run the test I am getting error message as Too many re-renders. React limits the number of renders to prevent an infinite loop.

What happened:

when run the test I am getting error message as Too many re-renders. React limits the number of renders to prevent an infinite loop.

Reproduction:

run the test as the code example above

Problem description:

The renderHook should support useMemo as part of custom hook implementation given it's quite common for the custom hook to have it.

Suggested solution:

The issue is not that useMemo is not working, it’s that the nums array being passed to the hook in the renderHook callback is a new reference every time it is called which triggered the memo dependencies to change which will call setIsGreater again which will trigger another render with a new nums reference, spiolnning forever in an infinite loop.

To fix, create the array outside of the fallback instead.

mzbac commented

Thanks for the helps @mpeyper, didn't notice the callback will be triggered for every re-rendering..