JotaiJotai

Jotai
React 原始而灵活的状态管理

atomWithBroadcast

atomWithBroadcast创建一个原子。这个原子将在浏览器的标签页和框架之间共享,类似于atomWithStorage,但是有初始化的限制。

这在你希望状态之间相互作用,而不使用localStorage的时候会很有用。 通过使用BroadcastChannel API,你可以在同一源上的窗口、标签、框架、组件或iframe,以及工作器之间启用基本的通信。 根据MDN文档,BroadcastChannel在初始化期间不支持接收消息,但是如果你想支持那个功能,你可能需要向atomWithBroadcast添加额外的选项,比如本地存储。

import { atom } from 'jotai'
export function atomWithBroadcast<Value>(key: string, initialValue: Value) {
const baseAtom = atom(initialValue)
const listeners = new Set<(event: MessageEvent<any>) => void>()
const channel = new BroadcastChannel(key)
channel.onmessage = (event) => {
listeners.forEach((l) => l(event))
}
const broadcastAtom = atom<Value, { isEvent: boolean; value: Value }>(
(get) => get(baseAtom),
(get, set, update) => {
set(baseAtom, update.value)
if (!update.isEvent) {
channel.postMessage(get(baseAtom))
}
},
)
broadcastAtom.onMount = (setAtom) => {
const listener = (event: MessageEvent<any>) => {
setAtom({ isEvent: true, value: event.data })
}
listeners.add(listener)
return () => {
listeners.delete(listener)
}
}
const returnedAtom = atom<Value, Value>(
(get) => get(broadcastAtom),
(get, set, update) => {
set(broadcastAtom, { isEvent: false, value: update })
},
)
return returnedAtom
}
const broadAtom = atomWithBroadcast('count', 0)
const ListOfThings = () => {
const [count, setCount] = useAtom(broadAtom)
return (
<div>
{count}
<button onClick={() => setCount(count + 1)}>+1</button>
</div>
)
}