Skip to content

Commit

Permalink
feat: ssr
Browse files Browse the repository at this point in the history
  • Loading branch information
jxom committed Oct 18, 2023
1 parent bb7365c commit 2ef5d1b
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 12 deletions.
26 changes: 23 additions & 3 deletions packages/core/src/createConfig.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { type EIP6963ProviderDetail, createStore as createMipd } from 'mipd'
import {
type EIP6963ProviderDetail,
type Store as MipdStore,
createStore as createMipd,
} from 'mipd'
import {
type Address,
type Chain,
Expand All @@ -8,7 +12,7 @@ import {
createClient,
} from 'viem'
import { persist, subscribeWithSelector } from 'zustand/middleware'
import { createStore } from 'zustand/vanilla'
import { type Mutate, type StoreApi, createStore } from 'zustand/vanilla'

import {
type ConnectorEventMap,
Expand All @@ -33,6 +37,7 @@ export type CreateConfigParameters<
connectors?: CreateConnectorFn[] | undefined
multiInjectedProviderDiscovery?: boolean | undefined
storage?: Storage | null | undefined
ssr?: boolean | undefined
syncConnectedChain?: boolean | undefined
} & OneOf<
| ({ transports: transports } & {
Expand Down Expand Up @@ -66,6 +71,7 @@ export function createConfig<
: noopStorage,
}),
syncConnectedChain = true,
ssr,
...rest
} = parameters

Expand All @@ -81,7 +87,9 @@ export function createConfig<
const connectors = createStore(() =>
[
...(rest.connectors ?? []),
...(mipd?.getProviders().map(providerDetailToConnector) ?? []),
...(!ssr
? mipd?.getProviders().map(providerDetailToConnector) ?? []
: []),
].map(setup),
)
function setup(connectorFn: CreateConnectorFn) {
Expand Down Expand Up @@ -174,10 +182,12 @@ export function createConfig<
name: 'store',
partialize(state) {
return {
connections: state.connections,
chainId: state.chainId,
current: state.current,
} satisfies PartializedState
},
skipHydration: ssr,
storage: storage as Storage<Record<string, unknown>>,
version: 1,
})
Expand Down Expand Up @@ -318,9 +328,13 @@ export function createConfig<
},

_internal: {
mipd,
store,
ssr: Boolean(ssr),
syncConnectedChain,
transports: rest.transports as transports,
connectors: {
providerDetailToConnector,
setup,
setState: (value) =>
connectors.setState(
Expand Down Expand Up @@ -369,10 +383,16 @@ export type Config<
}): Client<transports[chainId], Extract<chains[number], { id: chainId }>>

_internal: {
readonly mipd: MipdStore | undefined
readonly store: Mutate<StoreApi<any>, [['zustand/persist', any]]>
readonly ssr: boolean
readonly syncConnectedChain: boolean
readonly transports: transports

connectors: {
providerDetailToConnector(
providerDetail: EIP6963ProviderDetail,
): CreateConnectorFn
setup(connectorFn: CreateConnectorFn): Connector
setState(value: Connector[] | ((state: Connector[]) => Connector[])): void
subscribe(
Expand Down
1 change: 1 addition & 0 deletions packages/core/src/exports/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ test('exports', () => {
"createConfig",
"createStorage",
"noopStorage",
"rehydrate",
"BaseError",
"ChainMismatchError",
"ChainNotConfiguredError",
Expand Down
5 changes: 5 additions & 0 deletions packages/core/src/exports/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,11 @@ export {
noopStorage,
} from '../createStorage.js'

////////////////////////////////////////////////////////////////////////////////
// rehydrate

export { rehydrate } from '../rehydrate.js'

////////////////////////////////////////////////////////////////////////////////
// Errors

Expand Down
16 changes: 16 additions & 0 deletions packages/core/src/rehydrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import type { Config } from './createConfig.js'

export async function rehydrate(config: Config) {
if (!config._internal.ssr) return

await config._internal.store.persist.rehydrate()

const mipdConnectors = config._internal.mipd
?.getProviders()
.map(config._internal.connectors.providerDetailToConnector)
.map(config._internal.connectors.setup)
config._internal.connectors.setState((connectors) => [
...connectors,
...(mipdConnectors ?? []),
])
}
18 changes: 9 additions & 9 deletions packages/react/src/context.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client'

import { type ResolvedRegister, reconnect } from '@wagmi/core'
import { createContext, createElement, useEffect } from 'react'
import { type ResolvedRegister } from '@wagmi/core'
import { createContext, createElement } from 'react'
import { Rehydrate } from './rehydrate.js'

export const WagmiContext = createContext<
ResolvedRegister['config'] | undefined
Expand All @@ -15,13 +16,12 @@ export type WagmiProviderProps = {
export function WagmiProvider(
parameters: React.PropsWithChildren<WagmiProviderProps>,
) {
const { children, config, reconnectOnMount = true } = parameters

// biome-ignore lint/nursery/useExhaustiveDependencies: only run on mount
useEffect(() => {
if (reconnectOnMount) reconnect(config)
}, [])
const { children, config } = parameters

const props = { value: config }
return createElement(WagmiContext.Provider, props, children)
return createElement(
Rehydrate,
parameters,
createElement(WagmiContext.Provider, props, children),
)
}
31 changes: 31 additions & 0 deletions packages/react/src/rehydrate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
'use client'

import { type ResolvedRegister, reconnect, rehydrate } from '@wagmi/core'
import { useEffect, useRef } from 'react'

export type RehydrateProps = {
config: ResolvedRegister['config']
reconnectOnMount?: boolean | undefined
}

export function Rehydrate(parameters: React.PropsWithChildren<RehydrateProps>) {
const { children, config, reconnectOnMount = true } = parameters

if (!config._internal.ssr && reconnectOnMount) reconnect(config)

const active = useRef(true)
// biome-ignore lint/nursery/useExhaustiveDependencies:
useEffect(() => {
if (!active.current) return
if (!config._internal.ssr) return
;(async () => {
await rehydrate(config)
reconnect(config)
})()
return () => {
active.current = false
}
}, [])

return children
}
1 change: 1 addition & 0 deletions playgrounds/vite-ssr-react/lib/wagmi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export const config = createConfig({
ledger({ projectId: import.meta.env.VITE_WC_PROJECT_ID }),
safe({ debug: true, shimDisconnect: true }),
],
ssr: true,
storage: createStorage({
key: 'vite-ssr-react',
storage: typeof localStorage !== 'undefined' ? localStorage : undefined,
Expand Down

1 comment on commit 2ef5d1b

@vercel
Copy link

@vercel vercel bot commented on 2ef5d1b Oct 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

wagmi-v2 – ./docs

wagmi-v2-git-alpha-wagmi-dev.vercel.app
wagmi-v2-wagmi-dev.vercel.app
wagmi-v2.vercel.app
alpha.wagmi.sh

Please sign in to comment.