SSR
Wagmi uses client-only external stores (such as localStorage and mipd
) to show the user the most relevant data as quickly as possible on first render.
However, the caveat of using these external client stores is that frameworks which incorporate SSR (such as Next.js) will throw hydration warnings on the client when it identifies mismatches between the server-rendered HTML and the client-rendered HTML.
To stop this from happening, you can toggle on the ssr
property in the Wagmi Config.
import { createConfig, http } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
const config = createConfig({
chains: [mainnet, sepolia],
ssr: true,
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})
import { createConfig, http } from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
const config = createConfig({
chains: [mainnet, sepolia],
ssr: true,
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})
Turning on the ssr
property means that content from the external stores will be hydrated on the client after the initial mount.
Persistence using Cookies
As a result of turning on the ssr
property, external persistent stores like localStorage
will be hydrated on the client after the initial mount.
This means that you will still see a flash of "empty" data on the client (e.g. a "disconnected"
account instead of a "reconnecting"
account, or an empty address instead of the last connected address) until after the first mount, when the store hydrates.
In order to persist data between the server and the client, you can use cookies.
1. Set up cookie storage
First, we will set up cookie storage in the Wagmi Config.
import {
createConfig,
http,
cookieStorage,
createStorage
} from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
export const config = createConfig({
chains: [mainnet, sepolia],
ssr: true,
storage: createStorage({
storage: cookieStorage,
}),
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})
import {
createConfig,
http,
cookieStorage,
createStorage
} from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
export const config = createConfig({
chains: [mainnet, sepolia],
ssr: true,
storage: createStorage({
storage: cookieStorage,
}),
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})
2. Hydrate the cookie
Next, we will need to add some mechanisms to hydrate the stored cookie in Wagmi.
Next.js App Directory
In our app/layout.tsx
file (a Server Component), we will need to extract the cookie from the headers
function and pass it to cookieToInitialState
.
We will need to pass this result to the initialState
property of the WagmiProvider
. The WagmiProvider
must be in a Client Component tagged with "use client"
(see app/providers.tsx
tab).
import { type ReactNode } from 'react'
import { headers } from 'next/headers'
import { cookieToInitialState } from 'wagmi'
import { config } from './config'
import { Providers } from './providers'
export default function Layout({ children }: { children: ReactNode }) {
const initialState = cookieToInitialState(
config,
headers().get('cookie')
)
return (
<html lang="en">
<body>
<Providers>
<Providers initialState={initialState}>
{children}
</Providers>
</body>
</html>
)
}
import { type ReactNode } from 'react'
import { headers } from 'next/headers'
import { cookieToInitialState } from 'wagmi'
import { config } from './config'
import { Providers } from './providers'
export default function Layout({ children }: { children: ReactNode }) {
const initialState = cookieToInitialState(
config,
headers().get('cookie')
)
return (
<html lang="en">
<body>
<Providers>
<Providers initialState={initialState}>
{children}
</Providers>
</body>
</html>
)
}
'use client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import type { ReactNode } from 'react'
import { type State, WagmiProvider } from 'wagmi'
import { config } from './config'
type Props = {
children: ReactNode,
initialState: State | undefined,
}
const queryClient = new QueryClient()
export function Providers({ children }: Props) {
export function Providers({ children, initialState }: Props) {
return (
<WagmiProvider config={config}>
<WagmiProvider config={config} initialState={initialState}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
)
}
'use client'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import type { ReactNode } from 'react'
import { type State, WagmiProvider } from 'wagmi'
import { config } from './config'
type Props = {
children: ReactNode,
initialState: State | undefined,
}
const queryClient = new QueryClient()
export function Providers({ children }: Props) {
export function Providers({ children, initialState }: Props) {
return (
<WagmiProvider config={config}>
<WagmiProvider config={config} initialState={initialState}>
<QueryClientProvider client={queryClient}>
{children}
</QueryClientProvider>
</WagmiProvider>
)
}
import {
createConfig,
http,
cookieStorage,
createStorage
} from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
export const config = createConfig({
chains: [mainnet, sepolia],
ssr: true,
storage: createStorage({
storage: cookieStorage,
}),
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})
import {
createConfig,
http,
cookieStorage,
createStorage
} from 'wagmi'
import { mainnet, sepolia } from 'wagmi/chains'
export const config = createConfig({
chains: [mainnet, sepolia],
ssr: true,
storage: createStorage({
storage: cookieStorage,
}),
transports: {
[mainnet.id]: http(),
[sepolia.id]: http(),
},
})
Next.js Pages Directory
Would you like to contribute this content? Feel free to open a Pull Request!
Vanilla SSR
Would you like to contribute this content? Feel free to open a Pull Request!