fix: restructure web3 to memoize (#3472)

This commit is contained in:
Zach Pomerantz 2022-03-09 15:08:04 -08:00 committed by GitHub
parent 96c66a5846
commit 32f955693f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 64 additions and 71 deletions

@ -1,40 +0,0 @@
import { initializeConnector } from '@web3-react/core'
import { EIP1193 } from '@web3-react/eip1193'
import { Actions, Connector, Provider as Eip1193Provider } from '@web3-react/types'
import { Url } from '@web3-react/url'
import { SetStateAction } from 'jotai'
import { RESET, useUpdateAtom } from 'jotai/utils'
import { injectedAtom, urlAtom, Web3ReactState } from 'lib/state/web3'
import { ReactNode, useEffect } from 'react'
interface Web3ProviderProps {
jsonRpcEndpoint?: string
provider?: Eip1193Provider
children: ReactNode
}
function useConnector<T extends { new (actions: Actions, initializer: I): Connector }, I>(
Connector: T,
initializer: I | undefined,
setContext: (update: typeof RESET | SetStateAction<Web3ReactState>) => void
) {
return useEffect(() => {
if (initializer) {
const state = initializeConnector((actions) => new Connector(actions, initializer))
state[0].activate()
setContext(state)
} else {
setContext(RESET)
}
}, [Connector, initializer, setContext])
}
export default function Web3Provider({ jsonRpcEndpoint, provider, children }: Web3ProviderProps) {
const setUrl = useUpdateAtom(urlAtom)
useConnector(Url, jsonRpcEndpoint, setUrl)
const setInjected = useUpdateAtom(injectedAtom)
useConnector(EIP1193, provider, setInjected)
return <>{children}</>
}

@ -3,6 +3,7 @@ import { Provider as Eip1193Provider } from '@web3-react/types'
import { DEFAULT_LOCALE, SupportedLocale } from 'constants/locales' import { DEFAULT_LOCALE, SupportedLocale } from 'constants/locales'
import { Provider as AtomProvider } from 'jotai' import { Provider as AtomProvider } from 'jotai'
import { TransactionsUpdater } from 'lib/hooks/transactions' import { TransactionsUpdater } from 'lib/hooks/transactions'
import { Web3Provider } from 'lib/hooks/useActiveWeb3React'
import { BlockUpdater } from 'lib/hooks/useBlockNumber' import { BlockUpdater } from 'lib/hooks/useBlockNumber'
import useEip1193Provider from 'lib/hooks/useEip1193Provider' import useEip1193Provider from 'lib/hooks/useEip1193Provider'
import { UNMOUNTING } from 'lib/hooks/useUnmount' import { UNMOUNTING } from 'lib/hooks/useUnmount'
@ -15,7 +16,6 @@ import { Provider as ReduxProvider } from 'react-redux'
import { Modal, Provider as DialogProvider } from './Dialog' import { Modal, Provider as DialogProvider } from './Dialog'
import ErrorBoundary, { ErrorHandler } from './Error/ErrorBoundary' import ErrorBoundary, { ErrorHandler } from './Error/ErrorBoundary'
import WidgetPropValidator from './Error/WidgetsPropsValidator' import WidgetPropValidator from './Error/WidgetsPropsValidator'
import Web3Provider from './Web3Provider'
const WidgetWrapper = styled.div<{ width?: number | string }>` const WidgetWrapper = styled.div<{ width?: number | string }>`
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;

@ -1,19 +0,0 @@
import { Web3ReactHooks } from '@web3-react/core'
import { useAtomValue } from 'jotai/utils'
import { injectedAtom, urlAtom, Web3ReactState } from 'lib/state/web3'
export function useActiveWeb3ReactState(): Web3ReactState {
const injected = useAtomValue(injectedAtom)
const url = useAtomValue(urlAtom)
return injected[1].useIsActive() ? injected : url
}
export function useActiveWeb3ReactHooks(): Web3ReactHooks {
const [, hooks] = useActiveWeb3ReactState()
return hooks
}
export default function useActiveWeb3React() {
const { useProvider, useWeb3React } = useActiveWeb3ReactHooks()
return useWeb3React(useProvider())
}

@ -0,0 +1,63 @@
import { getPriorityConnector, initializeConnector, Web3ReactHooks } from '@web3-react/core'
import { EIP1193 } from '@web3-react/eip1193'
import { EMPTY } from '@web3-react/empty'
import { Actions, Connector, Provider as Eip1193Provider } from '@web3-react/types'
import { Url } from '@web3-react/url'
import { useAtom, WritableAtom } from 'jotai'
import { useAtomValue } from 'jotai/utils'
import { atomWithDefault, RESET, useUpdateAtom } from 'jotai/utils'
import { PropsWithChildren, useEffect } from 'react'
const [connector, hooks] = initializeConnector(() => EMPTY)
const EMPTY_CONNECTOR: [Connector, Web3ReactHooks] = [connector, hooks]
const urlConnectorAtom = atomWithDefault<[Connector, Web3ReactHooks]>(() => EMPTY_CONNECTOR)
const injectedConnectorAtom = atomWithDefault<[Connector, Web3ReactHooks]>(() => EMPTY_CONNECTOR)
const web3Atom = atomWithDefault<ReturnType<typeof hooks.useWeb3React>>(() => ({
connector: EMPTY_CONNECTOR[0],
library: undefined,
chainId: undefined,
account: undefined,
active: false,
error: undefined,
}))
export default function useActiveWeb3React() {
return useAtomValue(web3Atom)
}
function useConnector<T extends { new (actions: Actions, initializer: I): Connector }, I>(
connectorAtom: WritableAtom<[Connector, Web3ReactHooks], typeof RESET | [Connector, Web3ReactHooks]>,
Connector: T,
initializer: I | undefined
) {
const [connector, setConnector] = useAtom(connectorAtom)
useEffect(() => {
if (initializer) {
const [connector, hooks] = initializeConnector((actions) => new Connector(actions, initializer))
connector.activate()
setConnector([connector, hooks])
} else {
setConnector(RESET)
}
}, [Connector, initializer, setConnector])
return connector
}
interface Web3ProviderProps {
provider?: Eip1193Provider
jsonRpcEndpoint?: string
}
export function Web3Provider({ provider, jsonRpcEndpoint, children }: PropsWithChildren<Web3ProviderProps>) {
const injectedConnector = useConnector(injectedConnectorAtom, EIP1193, provider)
const urlConnector = useConnector(urlConnectorAtom, Url, jsonRpcEndpoint)
const priorityConnector = getPriorityConnector(injectedConnector, urlConnector)
const priorityProvider = priorityConnector.usePriorityProvider()
const priorityWeb3React = priorityConnector.usePriorityWeb3React(priorityProvider)
const setWeb3 = useUpdateAtom(web3Atom)
useEffect(() => {
setWeb3(priorityWeb3React)
}, [priorityWeb3React, setWeb3])
return <>{children}</>
}

@ -1,11 +0,0 @@
import { initializeConnector, Web3ReactHooks } from '@web3-react/core'
import { EMPTY } from '@web3-react/empty'
import { Connector, Web3ReactStore } from '@web3-react/types'
import { atomWithDefault } from 'jotai/utils'
export type Web3ReactState = [Connector, Web3ReactHooks, Web3ReactStore]
const EMPTY_CONNECTOR = initializeConnector(() => EMPTY)
export const urlAtom = atomWithDefault<Web3ReactState>(() => EMPTY_CONNECTOR)
export const injectedAtom = atomWithDefault<Web3ReactState>(() => EMPTY_CONNECTOR)