一个真的仅需一行代码就可以配置的 React 全局状态库,但是功能也仅限于此 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
MakinoharaShoko
V2EX    React

一个真的仅需一行代码就可以配置的 React 全局状态库,但是功能也仅限于此

  •  1
     
  •   MakinoharShoko
    MakinoharaShoko 2023-09-01 23:19:49 +08:00 2309 次点击
    这是一个创建于 769 天前的主题,其中的信息可能已经有所发展或是发生改变。

    https://github.com/MakinoharaShoko/react-usevalue-hook

    以下两个组件可以同步状态:

    import { useValueWithKey } from 'react-usevalue-hook'; function Comp1() { const value1 = useValueWithKey(1, 'global1') return <div OnClick={() => { value1.value = value1.value + 1 }}> {value1.value} Click to +1 </div> } function Comp2() { const value2 = useValueWithKey(2, 'global1') return <div OnClick={() => { value2.value = value2.value + 1 }}> {value2.value} Click to +1 </div> } function App() { return ( <div style={{padding:20}}> <div><Comp1 /></div> <div><Comp2 /></div> </div> ) } export default App 
    15 条回复    2023-09-03 19:53:00 +08:00
    SHF
        1
    SHF  
       2023-09-01 23:25:40 +08:00
    https://github.com/ShenHongFei/react-object-model

    我这个状态管理库也很简单,在组件里通过

    const { name, age } = user.use(['name', 'age'])

    订阅对象的属性,在属性改变时 diff, 重新渲染
    MakinoharaShoko
        2
    MakinoharaShoko  
    OP
       2023-09-01 23:40:41 +08:00
    @SHF 将一个对象转换为一个全局状态,挺有趣的
    SHF
        3
    SHF  
       2023-09-01 23:45:22 +08:00
    ```ts
    export function useValueWithKey<T> (initialState: T, key: string) {
    const [_, setValue] = useState<T>(initialState)

    useEffect(() => {
    // init value(if not set by another component)
    mkv.init(key, initialState)
    const handleChange = () => {
    setValue(mkv.get(key))
    }
    eb.on(`__CHANGED__${key}`, handleChange)
    handleChange()
    return () => {
    eb.off(`__CHANGED__${key}`, handleChange)
    }
    }, [ ])

    return {
    set value (newValue: T) {
    mkv.set(key, newValue)
    eb.emit(`__CHANGED__${key}`)
    setValue(newValue)
    },
    get value (): T {
    return mkv.get(key) ?? initialState
    }
    }
    }
    ```

    useEffect 里面直接调用了 handleChange, 里面执行 setValue 会导致组件挂载之后因为 state 变了又重新 render ,不太好
    你试试在组件里面 console.log('render') 看看渲染了几次
    yhvictor
        4
    yhvictor  
       2023-09-01 23:46:40 +08:00
    跟 jotai 差不多
    MakinoharaShoko
        5
    MakinoaraShoko  
    OP
       2023-09-01 23:49:33 +08:00
    @SHF #3 确实不太好,写这个是为了让两个不同初始值的状态能统一,如果不考虑这个问题就不用写这行代码了(我在想什么,给一个 key 的状态设置两个不同的初始值不是用户的问题吗)
    MakinoharaShoko
        6
    MakinoharaShoko  
    OP
       2023-09-01 23:51:31 +08:00
    @SHF #3 我来加个条件判断,如果获取到的结果等于初始值,就不设置
    SHF
        7
    SHF  
       2023-09-02 00:05:00 +08:00
    还有个问题,就是 MemoryKV 里面 map 里存了 key 对应的 value. 在 init 的时候添加进 map ,但是在所有使用这个 key 的组件都 unmount 时,应该删除 map 中的 key, 否则就会内存泄漏。map 除了要维护 value ,还要维护使用这个 key 的组件有多少,当使用的组件为 0 时做清理。但这个方法其实在 react 18 里面,如果启用了 strict 模式,组件会被模拟挂载两次,也不好搞,参考 https://stackoverflow.com/questions/72238175/why-useeffect-running-twice-and-how-to-handle-it-well-in-react
    MakinoharaShoko
        8
    MakinoharaShoko  
    OP
       2023-09-02 00:07:58 +08:00
    @SHF #7 确实有点不好搞,不过如果做成每次执行 useEffect 中的卸载函数时候 -1 ,每次 init 时 +1 ,应该可以解决
    MakinoharaShoko
        9
    MakinoharaShoko  
    OP
       2023-09-02 00:10:47 +08:00
    @SHF #7 不过这个库更多是用于在做小项目的时候偷懒,内存泄露只取决于 key 的数目,感觉也不会很庞大。我打算再优化优化
    MakinoharaShoko
        10
    MakinoharaShoko  
    OP
       2023-09-02 01:35:03 +08:00 via Android
    @SHF 突然想到一个问题,对于一个全局状态存储库,在组件卸载后把状态留下来,好像是一个正确的行为。其他全局状态存储库的状态初始化是和组件无关的,无论组件是否存在,状态都一直在内存中保留。而我这里只是把初始化放到了组件挂载过程中,其他行为应该要和其他全局状态存储库保持一致。
    SHF
        11
    SHF  
       2023-09-02 12:35:20 +08:00
    codehz
        12
    codehz  
       2023-09-02 13:06:34 +08:00
    useEffect 里搞订阅容易在 react18 的 suspense 和异步模式中出问题
    MakinoharaShoko
        13
    MakinoharaShoko  
    OP
       2023-09-02 22:33:12 +08:00
    @codehz 是的,但是官方教程(老)确实是这样做的,之后想到新办法再来解决一下
    codehz
        14
    codehz  
       2023-09-03 00:58:34 +08:00 via iPhone
    @MakinoharaShoko react18 有专门的 useSyncExternalStore
    MakinoharaShoko
        15
    MakinoharaShoko  
    OP
       2023-09-03 19:53:00 +08:00
    @codehz #14 OK ,我去了解一下
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     868 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 20:28 PVG 04:28 LAX 13:28 JFK 16:28
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86