-
Notifications
You must be signed in to change notification settings - Fork 26.7k
/
store.js
73 lines (65 loc) · 1.72 KB
/
store.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
import { useLayoutEffect } from 'react'
import create from 'zustand'
import createContext from 'zustand/context'
let store
const initialState = {
lastUpdate: 0,
light: false,
count: 0,
}
const zustandContext = createContext()
export const Provider = zustandContext.Provider
// An example of how to get types
/** @type {import('zustand/index').UseStore<typeof initialState>} */
export const useStore = zustandContext.useStore
export const initializeStore = (preloadedState = {}) => {
return create((set, get) => ({
...initialState,
...preloadedState,
tick: (lastUpdate, light) => {
set({
lastUpdate,
light: !!light,
})
},
increment: () => {
set({
count: get().count + 1,
})
},
decrement: () => {
set({
count: get().count - 1,
})
},
reset: () => {
set({
count: initialState.count,
})
},
}))
}
export function useHydrate(initialState) {
let _store = store ?? initializeStore(initialState)
// For SSR & SSG, always use a new store.
if (typeof window !== 'undefined') {
// For CSR, always re-use same store.
if (!store) {
store = _store
}
// And if initialState changes, then merge states in the next render cycle.
//
// eslint complaining "React Hooks must be called in the exact same order in every component render"
// is ignorable as this code runs in the same order in a given environment (CSR/SSR/SSG)
// eslint-disable-next-line react-hooks/rules-of-hooks
useLayoutEffect(() => {
if (initialState && store) {
store.setState({
...store.getState(),
...initialState,
})
}
}, [initialState])
}
return _store
}