wagmi
wagmi copied to clipboard
Hydrate component changes state while rendering, causing a react warning
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 insideHydrate, 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)
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
- Open browser devtools
- Clear any unrelated warnings etc from initial page load
- Click the "Change Root State" button in the page
- 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
- [X] I checked there isn't already an issue for the bug I encountered.
Anything else?
Can work around by hoisting the Wami context above any other contexts to prevent it re-rendering.
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
}
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.
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.