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

wagmi stays in the reconnecting: true state during the hot-reload #3490

Closed
1 task done
dalechyn opened this issue Jan 20, 2024 · 8 comments · Fixed by #3715
Closed
1 task done

wagmi stays in the reconnecting: true state during the hot-reload #3490

dalechyn opened this issue Jan 20, 2024 · 8 comments · Fixed by #3715

Comments

@dalechyn
Copy link
Collaborator

Describe the bug

When you're making any changes in nextjs routes, the app tries to hot reload and wagmi hands at the isReconnecting: true state:

Export-1705764560181.mp4

Link to Minimal Reproducible Example

https://github.com/dalechyn/mini-repros/tree/main/wagmi-hot-reload-infinite-reconnect

Steps To Reproduce

  1. pnpm dev
  2. Open src/app/revalidate/route.ts and make any change there
  3. Watch the connectors hang on hot-reload.

Wagmi Version

2.3.1

Viem Version

2.4.0

TypeScript Version

5.2.2

Check existing issues

Anything else?

Originally a similar bug (which I believe has a common root with issue) happened to me when I have used trpc's experimental app router library's revalidate method that revalidates a route by tag.

The same effect was achieved, yet I was not able to achieve the same effect with this repro outside of hot-reload, but when a revalidation happens from the server-side, wagmi suffers from the same reconnect hanging issue:

Export-1705765355451.mp4

Reference scrapped out code:

  const { address, isConnecting, isReconnecting, isConnected } = useAccount()

  const skeleton = (
    <Button {...rest} disabled>
      <Loader className="mr-1 w-4 h-4 animate-spin stroke-foreground" />
      Tip
    </Button>
  )

  if (isConnecting || isReconnecting)
    return (
      <>
        {skeleton}isConnecting: {isConnecting.toString()}isReconnecting:{' '}
        {isReconnecting.toString()}
      </>
    )
  if (!isConnected || !address) return <ConnectButton />

  return (
    <Suspense
      fallback={
        <>
          {skeleton}
          Suspense
        </>
      }
    >
      <Something />
    </Suspense>
  )
@keagancoding
Copy link

Any luck with this im getting a smiliar error where I have to reconnect my wallet every hot reload?

@dalechyn
Copy link
Collaborator Author

I've debugged a little bit and think that the issue is that the onMount is not being triggered because the active ref stays with value { current: false } on re-render, and because useEffect's dependencies don't change, therefore the onMount function is never called to hydrate wagmi.

I'm not that great in wagmi's codebase but I suppose that some connector-related state is being forcefully purged when it in fact should not be, and the onMount shouldn't even theoretically be called because the state should not have been purged therefore should not need a hydration.

Export-1705841309505.mp4

export function Hydrate(parameters: React.PropsWithChildren<HydrateProps>) {
const { children, config, initialState, reconnectOnMount = true } = parameters
const { onMount } = hydrate(config, {
initialState,
reconnectOnMount,
})
// Hydrate for non-SSR
if (!config._internal.ssr) onMount()
// Hydrate for SSR
const active = useRef(true)
// biome-ignore lint/nursery/useExhaustiveDependencies:
useEffect(() => {
if (!active.current) return
if (!config._internal.ssr) return
onMount()
return () => {
active.current = false
}
}, [])
return children as ReactElement
}

@dalechyn
Copy link
Collaborator Author

Any luck with this im getting a smiliar error where I have to reconnect my wallet every hot reload?

Your issue is a bit different I believe, make sure you're persisting wagmi state via cookies https://wagmi.sh/react/guides/ssr#persistence-using-cookies

@dalechyn
Copy link
Collaborator Author

I was able to modify the script the next way and now onMount is called on hot-reload.

 export function Hydrate(parameters: React.PropsWithChildren<HydrateProps>) { 
   const { children, config, initialState, reconnectOnMount = true } = parameters 
  
   const { onMount } = hydrate(config, { 
     initialState, 
     reconnectOnMount, 
   }) 
  
   // Hydrate for non-SSR 
   if (!config._internal.ssr) onMount() 
  
   // biome-ignore lint/nursery/useExhaustiveDependencies: 
   useEffect(() => { 
     if (!config._internal.ssr) return 
     onMount() 
   }, [onMount]) 
  
   return children as ReactElement 
 } 

As far as I've understood, the cont active = useRef(true) was there to really make sure the effect is run just once as React doesn't guarantee that an effect won't be re-run once again, yet for the same reason the dependencies were empty to minimize the redundant effect calls.

However, I think the effect still has to be run as during hot-reload component might get re-mounted.

Using this as a workaround for now.

dalechyn added a commit to dalechyn/wagmi that referenced this issue Jan 21, 2024
As far as I've understood, the `const active = useRef(true)` was there to really make sure the effect is run just once as React doesn't guarantee that an effect won't be re-run once again, and for the same reason the dependencies were empty to minimize the redundant effect calls.

However, I think the effect still has to be run as during hot-reload component might get remounted with all connectors hanging in `isReconnecting: true` state.

Using this as a workaround for now.

Might fix wevm#3490, yet also prune to excessive re-connects that might cause UI regressions, idk.
@dalechyn
Copy link
Collaborator Author

#3492 also fixes revalidate rerender issue that was mentioned in the "Anything else?" block.

@smauret
Copy link

smauret commented Mar 5, 2024

Hello, I'm getting that behaviour too, trying to do a web3 action after hot reload fails with TypeError: connection.connector.getProvider is not a function, do we know when this can be fixed ?

@kiknaio
Copy link

kiknaio commented Mar 14, 2024

Hello, I'm getting that behaviour too, trying to do a web3 action after hot reload fails with TypeError: connection.connector.getProvider is not a function, do we know when this can be fixed ?

I have exactly same issue. Have you fixed it?

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
4 participants