Skip to content

Commit 793d8da

Browse files
Aaron Cookmahmud-bn
andauthored
refactor: upgrade to React 18 + add useAppState (#915)
* refactor: upgrade to React 18 + add `useAppState` * fix: remove unnecessary comma + types version * fix: memoize callbacks * fix: use new types * fix: adjust dependencies + add shim * Merge branch 'v2-web3-onboard-develop' into refactor/useappstate * fix: shim import + `useSetChain` return * package bump * Delete yarn-error.log * package bump * package bump Co-authored-by: Mahmud <mahmud@blocknative.com> Co-authored-by: Mahmud <104795334+mahmud-bn@users.noreply.github.com>
1 parent d4fed9f commit 793d8da

File tree

3 files changed

+86
-74
lines changed

3 files changed

+86
-74
lines changed

packages/react/package.json

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@web3-onboard/react",
3-
"version": "2.1.7",
3+
"version": "2.1.7-alpha.1",
44
"description": "Collection of React Hooks for web3-onboard",
55
"module": "dist/index.js",
66
"browser": "dist/index.js",
@@ -17,14 +17,17 @@
1717
},
1818
"license": "MIT",
1919
"devDependencies": {
20-
"@types/react": "^17.0.39",
20+
"@types/react": "^18.0.2",
21+
"@types/use-sync-external-store": "^0.0.3",
22+
"react": "^18.0.0",
2123
"typescript": "^4.5.5"
2224
},
2325
"dependencies": {
24-
"@web3-onboard/core": "^2.2.9",
25-
"@web3-onboard/common": "^2.1.0"
26+
"@web3-onboard/core": "^2.2.10",
27+
"@web3-onboard/common": "^2.1.0-alpha.1",
28+
"use-sync-external-store": "1.0.0"
2629
},
2730
"peerDependencies": {
28-
"react": "^17.0.2"
31+
"react": ">=16.8"
2932
}
30-
}
33+
}

packages/react/src/index.ts

Lines changed: 56 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { useEffect, useState, useCallback, useMemo } from 'react'
1+
import { useState, useCallback } from 'react'
2+
import { useSyncExternalStore } from 'use-sync-external-store/shim'
23

34
import Web3Onboard from '@web3-onboard/core'
45
import type {
@@ -9,8 +10,8 @@ import type {
910
WalletState,
1011
ConnectedChain
1112
} from '@web3-onboard/core'
12-
13-
import { Chain } from '@web3-onboard/common'
13+
import type { Chain } from '@web3-onboard/common'
14+
import type { AppState } from '@web3-onboard/core/dist/types'
1415

1516
export let web3Onboard: OnboardAPI | null = null
1617

@@ -19,43 +20,62 @@ export const init = (options: InitOptions): OnboardAPI => {
1920
return web3Onboard
2021
}
2122

23+
const HOOK_ERROR_MESSAGE = 'Must initialize before using hooks.'
24+
25+
const useAppState: {
26+
(): AppState
27+
<K extends keyof AppState>(stateKey?: K): AppState[K]
28+
} = (stateKey = undefined) => {
29+
if (!web3Onboard) throw new Error(HOOK_ERROR_MESSAGE)
30+
31+
const { select, get } = web3Onboard.state
32+
33+
const subscribe = useCallback(
34+
(onStoreChange: () => void) => {
35+
const { unsubscribe } = stateKey
36+
? select(stateKey).subscribe(onStoreChange)
37+
: select().subscribe(onStoreChange)
38+
39+
return () => unsubscribe
40+
},
41+
[stateKey]
42+
)
43+
44+
const getSnapshot = useCallback(() => {
45+
const snapshot = get()
46+
return stateKey ? snapshot[stateKey] : snapshot
47+
}, [stateKey])
48+
49+
return useSyncExternalStore(subscribe, getSnapshot)
50+
}
51+
2252
export const useConnectWallet = (): [
2353
{ wallet: WalletState | null; connecting: boolean },
24-
(options: ConnectOptions) => Promise<void>,
54+
(options?: ConnectOptions) => Promise<void>,
2555
(wallet: DisconnectOptions) => Promise<void>
2656
] => {
27-
if (!web3Onboard) throw new Error('Must initialize before using hooks.')
57+
if (!web3Onboard) throw new Error(HOOK_ERROR_MESSAGE)
2858

29-
const [wallet, setConnectedWallet] = useState<WalletState | null>(
30-
() => (web3Onboard as OnboardAPI).state.get().wallets[0] || null
31-
)
32-
const [connecting, setConnecting] = useState(false)
59+
const { connectWallet, disconnectWallet } = web3Onboard
3360

34-
useEffect(() => {
35-
const subscription = (web3Onboard as OnboardAPI).state
36-
.select('wallets')
37-
.subscribe(wallets => setConnectedWallet(wallets[0] || null))
61+
const wallets = useAppState('wallets')
62+
const wallet = wallets[0] || null
3863

39-
return () => subscription.unsubscribe()
40-
}, [wallet])
64+
const [connecting, setConnecting] = useState<boolean>(false)
4165

42-
const connect = useCallback(async (options: ConnectOptions) => {
66+
const connect = useCallback(async (options?: ConnectOptions) => {
4367
setConnecting(true)
4468

45-
const [connectedWallet] = await (web3Onboard as OnboardAPI).connectWallet(
46-
options
47-
)
69+
await connectWallet(options)
4870

4971
setConnecting(false)
50-
setConnectedWallet(connectedWallet || null)
5172
}, [])
5273

53-
const disconnect = useCallback(async ({ label }) => {
74+
const disconnect = useCallback(async ({ label }: DisconnectOptions) => {
5475
setConnecting(true)
5576

56-
await (web3Onboard as OnboardAPI).disconnectWallet({ label })
77+
await disconnectWallet({ label })
5778

58-
setConnectedWallet(null)
5979
setConnecting(false)
6080
}, [])
6181

@@ -77,63 +97,35 @@ export const useSetChain = (
7797
},
7898
(options: SetChainOptions) => Promise<boolean>
7999
] => {
80-
if (!web3Onboard) throw new Error('Must initialize before using hooks.')
100+
if (!web3Onboard) throw new Error(HOOK_ERROR_MESSAGE)
81101

82-
const { state, setChain } = web3Onboard as OnboardAPI
83-
const [settingChain, setInProgress] = useState<boolean>(false)
84-
85-
const [connectedChain, setConnectedChain] = useState<ConnectedChain | null>(
86-
() => {
87-
const initialWallets = (web3Onboard as OnboardAPI).state.get().wallets
88-
if (initialWallets.length === 0) return null
89-
return (
90-
(
91-
initialWallets.find(({ label }) => label === walletLabel) ||
92-
initialWallets[0]
93-
).chains[0] || null
94-
)
95-
}
96-
)
102+
const { setChain } = web3Onboard
97103

98-
const chains = useMemo(() => state.get().chains, [])
104+
const { wallets, chains } = useAppState()
99105

100-
useEffect(() => {
101-
const subscription = state.select('wallets').subscribe(wallets => {
102-
const wallet =
103-
wallets.find(({ label }) => label === walletLabel) || wallets[0]
106+
const connectedChain =
107+
(walletLabel
108+
? wallets.find(({ label }) => label === walletLabel)
109+
: wallets[0]
110+
)?.chains[0] || null
104111

105-
wallet && setConnectedChain(wallet.chains[0])
106-
})
107-
108-
return () => subscription.unsubscribe()
109-
}, [])
112+
const [settingChain, setInProgress] = useState<boolean>(false)
110113

111-
const set = useCallback(async (options: SetChainOptions): Promise<boolean> => {
114+
const set = useCallback(async (options: SetChainOptions) => {
112115
setInProgress(true)
113116

114117
const success = await setChain({ ...options, wallet: walletLabel })
115118

116119
setInProgress(false)
117120

118-
return success;
121+
return success
119122
}, [])
120123

121124
return [{ chains, connectedChain, settingChain }, set]
122125
}
123126

124127
export const useWallets = (): WalletState[] => {
125-
if (!web3Onboard) throw new Error('Must initialize before using hooks.')
126-
127-
const [wallets, setConnectedWallets] = useState<WalletState[]>(
128-
() => (web3Onboard as OnboardAPI).state.get().wallets
129-
)
130-
131-
useEffect(() => {
132-
const wallets$ = (web3Onboard as OnboardAPI).state.select('wallets')
133-
const subscription = wallets$.subscribe(setConnectedWallets)
134-
135-
return () => subscription.unsubscribe()
136-
}, [])
128+
if (!web3Onboard) throw new Error(HOOK_ERROR_MESSAGE)
137129

138-
return wallets
130+
return useAppState('wallets')
139131
}

yarn.lock

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1649,10 +1649,10 @@
16491649
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc"
16501650
integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==
16511651

1652-
"@types/react@^17.0.39":
1653-
version "17.0.43"
1654-
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.43.tgz#4adc142887dd4a2601ce730bc56c3436fdb07a55"
1655-
integrity sha512-8Q+LNpdxf057brvPu1lMtC5Vn7J119xrP1aq4qiaefNioQUYANF/CYeK4NsKorSZyUGJ66g0IM+4bbjwx45o2A==
1652+
"@types/react@^18.0.2":
1653+
version "18.0.9"
1654+
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.0.9.tgz#d6712a38bd6cd83469603e7359511126f122e878"
1655+
integrity sha512-9bjbg1hJHUm4De19L1cHiW0Jvx3geel6Qczhjd0qY5VKVE2X5+x77YxAepuCwVh4vrgZJdgEJw48zrhRIeF4Nw==
16561656
dependencies:
16571657
"@types/prop-types" "*"
16581658
"@types/scheduler" "*"
@@ -1711,6 +1711,11 @@
17111711
dependencies:
17121712
"@types/node" "*"
17131713

1714+
"@types/use-sync-external-store@^0.0.3":
1715+
version "0.0.3"
1716+
resolved "https://registry.yarnpkg.com/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz#b6725d5f4af24ace33b36fafd295136e75509f43"
1717+
integrity sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA==
1718+
17141719
"@types/ws@^8.2.2":
17151720
version "8.2.3"
17161721
resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.2.3.tgz#0bca6b03ba2f41e0fab782d4a573fe284aa907ae"
@@ -7782,6 +7787,13 @@ react@16.13.1:
77827787
object-assign "^4.1.1"
77837788
prop-types "^15.6.2"
77847789

7790+
react@^18.0.0:
7791+
version "18.0.0"
7792+
resolved "https://registry.yarnpkg.com/react/-/react-18.0.0.tgz#b468736d1f4a5891f38585ba8e8fb29f91c3cb96"
7793+
integrity sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==
7794+
dependencies:
7795+
loose-envify "^1.1.0"
7796+
77857797
readable-stream@^1.0.33:
77867798
version "1.1.14"
77877799
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9"
@@ -9218,6 +9230,11 @@ url@^0.11.0:
92189230
punycode "1.3.2"
92199231
querystring "0.2.0"
92209232

9233+
use-sync-external-store@1.0.0:
9234+
version "1.0.0"
9235+
resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.0.0.tgz#d98f4a9c2e73d0f958e7e2d2c2bfb5f618cbd8fd"
9236+
integrity sha512-AFVsxg5GkFg8GDcxnl+Z0lMAz9rE8DGJCc28qnBuQF7lac57B5smLcT37aXpXIIPz75rW4g3eXHPjhHwdGskOw==
9237+
92219238
utf-8-validate@^5.0.2:
92229239
version "5.0.8"
92239240
resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-5.0.8.tgz#4a735a61661dbb1c59a0868c397d2fe263f14e58"

0 commit comments

Comments
 (0)