Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hydrate component changes state while rendering, causing a react warning #3611

Closed
1 task done
h4l opened this issue Feb 18, 2024 · 3 comments · Fixed by #3715
Closed
1 task done

Hydrate component changes state while rendering, causing a react warning #3611

h4l opened this issue Feb 18, 2024 · 3 comments · Fixed by #3715

Comments

@h4l
Copy link

h4l commented Feb 18, 2024

Describe the bug

The Hydrate component performs state mutations while rendering, which react detects and logs the https://reactjs.org/link/setstate-in-render warning/error.

Warning: Cannot update a component (App) while rendering a different component (Hydrate). To locate the bad setState() call inside Hydrate, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
at Hydrate (http://localhost:5173/node_modules/.vite/deps/wagmi.js?v=fdedff45:349:11)
at WagmiProvider (http://localhost:5173/node_modules/.vite/deps/wagmi.js?v=fdedff45:373:11)
at Root (http://localhost:5173/src/App.tsx?t=1708235152875:22:24)

image

Seems to originate here: https://github.com/wevm/wagmi/blob/main/packages/react/src/hydrate.ts#L21

For some reason Hydrate calls onMount() inside a useEffect in the server side, but not in a useEffect on the client side. I've not read through the code to understand why, but presumably this error wouldn't occur if the call was made from a useEffect.

Link to Minimal Reproducible Example

https://stackblitz.com/edit/new-wagmi-judl71

Steps To Reproduce

  1. Open browser devtools
  2. Clear any unrelated warnings etc from initial page load
  3. Click the "Change Root State" button in the page
  4. Observe a React error in the console that Hydrate changed state while rendering

The Change Root State button here is triggering a render of the component that hosts Wagmi's context, which causes Hydrate to re-render and perform its state-change.

Note, sourcemaps don't seem to work in the stackblitz version, I made a repo here with the same that works locally: https://github.com/h4l/wagmi-impure-render-bug

Wagmi Version

2.5.7

Viem Version

2.7.10

TypeScript Version

5.3.3

Check existing issues

Anything else?

Can work around by hoisting the Wami context above any other contexts to prevent it re-rendering.

@glitch-txs
Copy link
Collaborator

glitch-txs commented Feb 18, 2024

mmm I'm not able to run Wagmi yet, but yep onMount should only be called once, so when the App component rerenders might cause this, regardless, rerendering your App component is usually bad practice because you're rerendering your whole application.

It shouldn't be called in a useEffect because the idea is to hydrate the store during page load, but should be called once

possible fix might be

  const active = useRef(true)
  
  // Hydrate for non-SSR
  if (!config._internal.ssr && active.current){
    onMount()
    active.current = false
  }

@h4l
Copy link
Author

h4l commented Feb 18, 2024

Thanks. FWIW, when I triggered it, it was because I mistakenly had some state above the WagmiProvider which shouldn't/didn't need to be there.

Copy link
Contributor

github-actions bot commented Apr 2, 2024

This issue has been locked since it has been closed for more than 14 days.

If you found a concrete bug or regression related to it, please open a new bug report with a reproduction against the latest wagmi version. If you have any other comments you can create a new discussion.

@github-actions github-actions bot locked and limited conversation to collaborators Apr 2, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants