跳到主要内容

useGlobalState

· 阅读需 2 分钟
Slipeda

状态在多组件传递

通常是:

  • 第三方库
  • context
  • props 传递

还可以手撸一个 useGlobalState

useGlobalState

使用 react17 实现

import { useState, useEffect, useCallback } from 'react'

export function createState(initialValue) {
return {
listeners: [],
state: initialValue,
}
}

export function useGlobalState(config) {
const [state, _setState] = useState(config.state)
const setState = useCallback((stateOrSetter) => {
let next = stateOrSetter
if (typeof stateOrSetter === 'function') {
next = stateOrSetter(config.state)
}
config.listeners.forEach((l) => l(next))
config.state = next
}, [])

useEffect(() => {
// Register the observer
const listener = (state) => _setState(state)
config.listeners.push(listener)

// Cleanup when unmounting
return () => {
const index = config.listeners.indexOf(listener)
config.listeners.splice(index, 1)
}
}, [])

return [state, setState]
}

使用:

const COUNT = createState(0)

const [count, setCount] = useGlobalState(COUNT)

使用 react 18 实现

import { useCallback, useSyncExternalStore } from 'react'

export function createState(initialValue) {
return {
listeners: [],
state: initialValue,
}
}

export function useGlobalState(config) {
const setState = useCallback((stateOrSetter) => {
let next = stateOrSetter
if (typeof stateOrSetter === 'function') {
next = stateOrSetter(config.state)
}
config.state = next
config.listeners.forEach((l) => l())
}, [])

const state = useSyncExternalStore(
(listener) => {
config.listeners.push(listener)
return () => config.listeners.filter((l) => l !== listener)
},
() => {
return config.state
}
)
return [state, setState]
}

使用:

const COUNT = createState(0)

const [count, setCount] = useGlobalState(COUNT)