family / connectkit

Connecting a wallet, made simple.
https://docs.family.co/connectkit
BSD 2-Clause "Simplified" License
848 stars 182 forks source link

[BUG] Warning: React has detected a change in the order of Hooks called by ConnectKitProvider. #356

Closed Haavi97 closed 7 months ago

Haavi97 commented 7 months ago

Describe the bug

I tried to migrate connectkit together with other libraries to the last versions and my dapp broke. I'm having problems with Alchemy provider and with the connect wallet when I cannot Metamask. I think somewhere I might have some client side component on server side but I cannot find where.

VM41530:12 Warning: React has detected a change in the order of Hooks called by ConnectKitProvider. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks

   Previous render            Next render
   ------------------------------------------------------
1. useContext                 useContext
2. useContext                 useContext
3. useContext                 useContext
4. useEffect                  useEffect
5. useContext                 useContext
6. useContext                 useContext
7. useSyncExternalStore       useSyncExternalStore
8. useState                   useState
9. useState                   useState
10. useState                  useState
11. useState                  useState
12. useState                  useState
13. useState                  useState
14. useState                  useState
15. useState                  useState
16. useState                  useState
17. useEffect                 useEffect
18. useEffect                 useEffect
19. useEffect                 useEffect
20. useContext                useContext
21. useRef                    useRef
22. useRef                    useRef
23. useMemo                   useMemo
24. useSyncExternalStore      useSyncExternalStore
25. useEffect                 useEffect
26. useDebugValue             useDebugValue
27. useEffect                 useContext
   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

    at ConnectKitProvider (webpack-internal:///(app-pages-browser)/./node_modules/connectkit/build/index.es.js:15605:11)
    at QueryClientProvider (webpack-internal:///(app-pages-browser)/./node_modules/@tanstack/react-query/build/modern/QueryClientProvider.js:27:11)
    at Hydrate (webpack-internal:///(app-pages-browser)/./node_modules/wagmi/dist/esm/hydrate.js:12:13)
    at WagmiProvider (webpack-internal:///(app-pages-browser)/./node_modules/wagmi/dist/esm/context.js:13:13)
    at html
    at RootLayout (webpack-internal:///(app-pages-browser)/./app/layout.jsx:33:11)
    at RedirectErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:73:9)
    at RedirectBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/redirect-boundary.js:81:11)
    at NotFoundErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:76:9)
    at NotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/not-found-boundary.js:84:11)
    at DevRootNotFoundBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/dev-root-not-found-boundary.js:33:11)
    at ReactDevOverlay (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/internal/ReactDevOverlay.js:84:9)
    at HotReload (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/react-dev-overlay/hot-reloader-client.js:307:11)
    at Router (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:181:11)
    at ErrorBoundaryHandler (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:114:9)
    at ErrorBoundary (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/error-boundary.js:161:11)
    at AppRouter (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/components/app-router.js:536:13)
    at ServerRoot (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:129:11)
    at RSCComponent
    at Root (webpack-internal:///(app-pages-browser)/./node_modules/next/dist/client/app-index.js:145:11)

To reproduce

My RootLayout code where I setup connectkit

"use client";
import React from "react";
import { WagmiProvider, createConfig, http } from "wagmi";
import { ConnectKitProvider, getDefaultConfig } from "connectkit";
import { Toaster } from "react-hot-toast";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

import "./i18n.jsx";

import Navbar from "../components/navigation/navbar";
import Footer from "../components/navigation/footer";
import {
  // mainnet,
  // polygon,
  // optimism,
  // arbitrum,
  polygonMumbai,
} from "wagmi/chains";

// Choose which chains you'd like to show
const chains = [polygonMumbai]; //, polygon, mainnet, optimism, arbitrum];

export default function RootLayout({ children }) {
  const config = createConfig(
    getDefaultConfig({
      chains,
      transports: {
        [polygonMumbai.id]: http(
          `https://polygon-mumbai.g.alchemy.com/v2/${process.env.NEXT_PUBLIC_ALCHEMY_API_KEY}`
        ),
      },
      // Required API Keys
      walletConnectProjectId: process.env.NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID,

      // Required
      appName: "Account Abstraction interaction Dapp",

      // Optional
      appDescription: "Your App Description",
      appUrl: "https://family.co", // your app's url
      appIcon: "https://family.co/logo.png", // your app's logo,no bigger than 1024x1024px (max. 1MB)
    })
  );

  const queryClient = new QueryClient();

  return (
    <html lang="en">
      <WagmiProvider config={config}>
        <QueryClientProvider client={queryClient}>
          <ConnectKitProvider mode="dark">
            <body>
              <Toaster position="bottom-right" />
              <Navbar />
              <div
                style={{
                  display: "flex",
                  flexDirection: "column",
                  minHeight: "105vh",
                }}
              >
                <div style={{ flexGrow: 1 }}>{children}</div>
                <Footer />
              </div>
            </body>
          </ConnectKitProvider>
        </QueryClientProvider>
      </WagmiProvider>
    </html>
  );
}

My code setting up Alchemy provider (using AA):

import { createWalletClient, custom } from "viem";
import { AlchemyProvider } from "@alchemy/aa-alchemy";
import { WalletClientSigner } from "@alchemy/aa-core";
import {
  LightSmartContractAccount,
  getDefaultLightAccountFactoryAddress,
} from "@alchemy/aa-accounts";
import { polygonMumbai } from "viem/chains";

const chain = polygonMumbai;

function useAAProvider() {
  const getProvider = async () => {
    const provider = new AlchemyProvider({
      apiKey: process.env.NEXT_PUBLIC_ALCHEMY_API_KEY,
      chain: chain,
    });
    return provider;
  };

  const createEOASigner = () => {
    const client = createWalletClient({
      chain: polygonMumbai,
      transport: custom(window.ethereum),
    });

    // this can now be used as an owner for a Smart Contract Account
    const eoaSigner = new WalletClientSigner(
      client,
      "json-rpc" //signerType
    );

    return eoaSigner;
  };

  const connectProviderWithSCAAddress = async (accountAddress) => {
    const provider = await getProvider();
    const eoaSigner = createEOASigner();
    const connectedProvider = await provider.connect(
      (rpcClient) =>
        new LightSmartContractAccount({
          chain,
          owner: eoaSigner,
          accountAddress: accountAddress,
          factoryAddress: getDefaultLightAccountFactoryAddress(chain),
          rpcClient,
        })
    );
    return connectedProvider;
  };

  const connectProvider = async (scaAddress) => {
    const provider = await getProvider();
    const eoaSigner = createEOASigner();

    const connectedProvider = await provider.connect(
      (rpcClient) =>
        new LightSmartContractAccount({
          chain,
          owner: eoaSigner,
          accountAddress: scaAddress ? scaAddress : undefined,
          factoryAddress: getDefaultLightAccountFactoryAddress(chain),
          rpcClient,
        })
    );
    return connectedProvider;
  };
  return { connectProviderWithSCAAddress, connectProvider };
}

export default useAAProvider;

connectkit version 1.7.1

Expected behavior

Not see any error and being able to use the connectkit provider for the signer in the account abstraction Alchemy provider as I could do with previous version of connectkit

Screenshots

If applicable, add screenshots to help explain your problem.

Environment details

OS: Windows Browser: Opera

Additional context

Next.js application

I have another error that might be related and I also haven't solved yet. I actually think this one is also caused by connectkit. This is the traceback:

TypeError: Cannot read properties of undefined (reading 'http')
    at new AlchemyProvider (base.js:61:90)
    at getProvider (useAAProvider.jsx:15:22)
    at connectProvider (useAAProvider.jsx:54:28)
    at getProvider (index.jsx:80:30)
    at eval (index.jsx:59:7)
    at commitHookEffectListMount (react-dom.development.js:18071:39)
    at commitHookPassiveMountEffects (react-dom.development.js:19742:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19826:29)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19824:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
    at recursivelyTraversePassiveMountEffects (react-dom.development.js:19808:21)
    at commitPassiveMountOnFiber (react-dom.development.js:19918:25)
lekevicius commented 7 months ago

I think this was fixed #349, but not yet released.

We're waiting on connectkit release to upgrade our stack.

lochie commented 7 months ago

Just released this fix in ConnectKit 1.7.2, sorry about the delay!