vitest-dev / vitest

Next generation testing framework powered by Vite.
https://vitest.dev
MIT License
13.17k stars 1.19k forks source link

Preact + @tanstack/react-query returns TypeError: Cannot read properties of null (reading 'useEffect') #5004

Open xleepy opened 10 months ago

xleepy commented 10 months ago

Describe the bug

Hi, Trying to use useQuery with preact + vite and cannot run tests because of error TypeError: Cannot read properties of null (reading 'useEffect') Tried to apply different approaches but vitest still fails and looks like cannot apply preact/compat alias but dev/build works as expected.

Reproduction

Repository: https://github.com/xleepy/recipes-app Steps to reproduce: npm install npm run generate-api npm run test

System Info

System:
    OS: Windows 10 10.0.19045
    CPU: (16) x64 AMD Ryzen 7 5800X3D 8-Core Processor
    Memory: 20.09 GB / 31.91 GB
  Binaries:
    Node: 18.16.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD
    npm: 9.5.1 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: Chromium (120.0.2210.133)
    Internet Explorer: 11.0.19041.3636

Used Package Manager

npm

Validations

hi-ogawa commented 10 months ago

Thanks for the reproduction. The difference of the effect of resolve.alias between Vite (client) and Vitest is somewhat expected with a similar caveat as Vite (ssr) external https://vitejs.dev/guide/ssr.html#ssr-externals

I haven't tried your repro yet (since it didn't look exactly minimal), but from the quick look, maybe some deep dependency could be installing react instead of preact. Can you try "overrides": { ... } https://docs.npmjs.com/cli/v9/configuring-npm/package-json#overrides to make sure all dependencies see preact?

xleepy commented 10 months ago

Will give a try. Thanks! Also additional note i already tried test.alias https://vitest.dev/config/#alias but without success

xleepy commented 10 months ago

Updated repo with overrides but still no luck https://github.com/xleepy/recipes-app/commit/8ea1eb16001cdaae3062ec0e2d15e19f7e7ba2f8

c-vetter commented 4 months ago

I'm running into this as well in a react project, with vitest@2.0.3 and vitest@2.0.5, also vitest@1.6.0.


Repro based on the basic boilerplate: https://stackblitz.com/edit/vitest-dev-vitest-hps856

Repro based on the react boilerplate, with basic code copied over: https://stackblitz.com/edit/vitest-dev-vitest-hi7ytz


Any test importing and calling use* from the react package, directly or via the subject under test, breaks with this error:

TypeError: Cannot read properties of null (reading 'use*')

And the error location is wrong in each case.

There is one exception in the react-based repro:

 FAIL  test/basic.test.tsx > useSquared
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
 ❯ Object.throwInvalidHookError node_modules/react-dom/cjs/react-dom.development.js:15408:9
 ❯ Proxy.useState node_modules/react/cjs/react.development.js:1622:21
 ❯ Module.useSquared src/basic.ts:4:15
      2| 
      3| export function useSquared(n: number) {
      4|   const [x] = useState(n);
       |               ^
      5| 
      6|   return x * x;
 ❯ eval test/basic.test.tsx:15:10

Note that this usage follows React's Rules of Hooks, so this might actually point to the cause, although I still cannot seem to determine that myself.


Interestingly, this only seems to happen for hooks. isValidElement from react does not cause this issue.

Additionally note that the useState inside theLink` component does not cause the issue either.


4000 describes the same issue and the repro there still shows this: https://stackblitz.com/edit/vitest-dev-vitest-ff6sbs

hi-ogawa commented 4 months ago

@c-vetter Your issue is likely different. React simply doesn't allow calling hooks outside of component ("rendering context" or whatever they call it). Here is a quick example and your usages of hooks are essentially same:

$ node -e 'require("react").useState(0)'
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://react.dev/link/invalid-hook-call for tips about how to debug and fix this problem.
/home/hiroshi/code/personal/vite-plugins/node_modules/.pnpm/react@19.0.0-rc-df5f2736-20240712/node_modules/react/cjs/react.development.js:1533
      return resolveDispatcher().useState(initialState);
                                ^

TypeError: Cannot read properties of null (reading 'useState')
    at process.env.NODE_ENV.exports.useState (/home/hiroshi/code/personal/vite-plugins/node_modules/.pnpm/react@19.0.0-rc-df5f2736-20240712/node_modules/react/cjs/react.development.js:1533:33)
    at [eval]:1:18
    at runScriptInThisContext (node:internal/vm:209:10)
    at node:internal/process/execution:118:14
    at [eval]-wrapper:6:24
    at runScript (node:internal/process/execution:101:62)
    at evalScript (node:internal/process/execution:133:3)
    at node:internal/main/eval_string:51:3

Node.js v20.14.0

It looks like Vitest's error stacktrace is odd, but again that's a different topic from the current issue which is about the intricacy of preact alias and Vite SSR.

c-vetter commented 3 months ago

@hi-ogawa You are correct, my issue results from failing to use renderHook which I failed to realize at the end of a long work week. A colleague found the issue and everything is working as intended. Thank you for your feedback.