react-testing-library icon indicating copy to clipboard operation
react-testing-library copied to clipboard

`RenderHookResult` doesn't match return value of `renderHook`

Open mattbrandlysonos opened this issue 3 years ago • 1 comments

  • @testing-library/react version: 13.3.0
  • Testing Framework and version: [email protected]
  • DOM Environment: jsdom

Relevant code or config:

If I write a small renderHook test and log the result.current value immediately after calling renderHook, this will show that the value is null.

const { result } = renderHook(() => useMyHook())
console.log(result.current) // => null

According to the provided RenderHookResult type, that value should be of type Result, but null is not a valid instance of type Result.

https://github.com/testing-library/react-testing-library/blob/c80809a956b0b9f3289c4a6fa8b5e8cc72d6ef6d/types/index.d.ts#L101-L114

Suggested solution:

Either the type could be updated:

current: Result | null

Or the renderHook implementation could change such that it synchronously returns a value of type Result.

mattbrandlysonos avatar Aug 22 '22 15:08 mattbrandlysonos

It doesn't look like this bug report has enough info for one of us to reproduce it.

Please provide a CodeSandbox (https://react.new), or a link to a repository on GitHub.

Here are some tips for providing a minimal example: https://stackoverflow.com/help/mcve

eps1lon avatar Sep 04 '22 16:09 eps1lon

@eps1lon This happens if there's an act call within the hook call stack.

E.g.,

const { result } = renderHook(() => {
  act(() => {});
  return { data: 1 };
});
// this is true, but probably shouldn't be
result.current === null;

https://codesandbox.io/s/gifted-fire-n8scc9?file=/index.test.js

I don't know how to turn this sandbox into a test runner as it tries to run react in the window instead.

ntucker avatar Jan 06 '23 11:01 ntucker

@ntucker Calling act within a hook is a bit odd considering act is a testing utility. It doesn't even work in production.

I'll try to figure out why it behaves at runtime like this. Ideally, we'd warn about it I think.

Could you elaborate why you're using act inside a hook?

eps1lon avatar Jan 07 '23 14:01 eps1lon

Could you elaborate why you're using act inside a hook?

Async callstack (say a network response) triggering setstate. Since it's async the test itself cannot be inlining the act call. This is achieved to only occur during tests as the test setup has dependency injection

ntucker avatar Jan 07 '23 14:01 ntucker

Could you give a complete example for this? I don't really see why the nested act is required as opposed to waiting with e.g. waitFor

eps1lon avatar Jan 07 '23 14:01 eps1lon

According to https://reactjs.org/docs/test-utils.html#act it "This makes your test run closer to how React works in the browser." I don't really know what that means, but I assume that means it flushes the macro task buffer for batched renders. Without it the react updates don't happen.

ntucker avatar Jan 07 '23 15:01 ntucker

Closing since this is unrelated to types and you don't need to run act inside hooks (since it's a dev-only tool).

eps1lon avatar Feb 16 '23 17:02 eps1lon