Closed mushan0x0 closed 2 years ago
@brickspert 有什么意见不
@awmleer
关于全局状态管理,我们建议使用 hox,ahooks 里不建议加这个 Hooks
感谢 RFC 哈!
@brickspert 这个不一样,你看下里面的源码呢 https://codesandbox.io/s/dumi-demo-forked-73u0pv?file=/useGlobalState.tsx
这个是用批量更新实现的全局状态,不是用的context
实现是用全局的一个 globalStates 去管理,相当于脱离了 React 的范围之外了,这样好么?
那我用 Context 去管理岂不是更好么,感觉不到优势在哪呢
可以实现组件卸载可以清除globalStates里面存的内容,优势在于不需要provider,useContext,createContext @hchlq
我的意思不是 ”组件卸载可以清除里面存的内容“。如果是 React 18 之后的,该如何考虑,状态管理是不建议脱离 React 的范围的
而且 createContext 我也可以封装,使用也很方便呀
我以为你考虑的是内存泄漏的问题,你可以举例说明可能会有什么问题吗 @hchlq
createContext 容易被滥用,开发者可能会往里面放很多东西,useGlobalState设计跟useState是一样的,可以防止这一点
没有特别好的举例,但是状态尽量不要脱离 React 的范围~
滥用是相对而言的,团队中通过一些开发原则就可以避免了
但是这样也没有脱离react范围,实际设置状态和读取状态都是react的useState
但是你会间接额外的维护状态和更新函数呀,我觉得不是特别有必要,看下 @brickspert 怎么说~
你的 demo 看起来比较简单,怎么处理多个数据呢
比如有 Global-A、 Global-B、Global-C,看起来得这样..?
const useGlobalA = () => useGlobalState('A');
const useGlobalB = () => useGlobalState('B');
const useGlobalC = () => useGlobalState('C');
const A = () => {
const [globalA] = useGlobalA();
const [globalB] = useGlobalB();
const [globalC] = useGlobalC();
return <div>组件A:{globalA}{globalB}{globalC}</div>;
};
@miracles1919 是的,它跟useState一样,只不过多了个key
那感觉实用性不是很大啊... 真实的场景下往往是需要聚合多组数据的,个人觉得没有必要加在 ahooks 里
关于全局状态管理,我们推荐使用 hox
多个数据组合也可以这样用,useState可以怎么用,它就可以怎么用
const useGlobalABC = () => {
const [globalA] = useGlobalState('A');
const [globalB] = useGlobalState('B');
const [globalC] = useGlobalState('C');
return { globalA, globalB, globalC };
};
const A = () => {
const {globalA, globalB, globalC} = useGlobalABC();
return <div>组件A:{globalA}{globalB}{globalC}</div>;
};
@miracles1919 组合使用的例子我加了,你看看
我有个小问题,如果在多个组件中都调用了 useGlobalState
,key
是同一个,但是 initialValue
值不一样,这种情况感觉还挺有问题的?
const Foo = () => {
const [counter, setCounter] = useGlobalState('counter', 1)
// ...
}
const Bar = () => {
const [counter, setCounter] = useGlobalState('counter', 2)
// ...
}
我有个小问题,如果在多个组件中都调用了
useGlobalState
,key
是同一个,但是initialValue
值不一样,这种情况感觉还挺有问题的?const Foo = () => { const [counter, setCounter] = useGlobalState('counter', 1) // ... } const Bar = () => { const [counter, setCounter] = useGlobalState('counter', 2) // ... }
key重复是不好避免的问题,但是像useLocalStorage这些都是用的key,大家普遍在用一般不会遇到什么问题。初始值只会在第一个使用到的地方才会生效,这个容易让用户困惑,但是可以加一些警告说初始值没有生效来避免
这么说的话... useLocalStorage 完全能代替啊
这么说的话... useLocalStorage 完全能代替啊
useLocalStorage不会更新所有用到的地方啊....你看看例子呢。而且有全局状态需求的地方并不一定有存储local storage的需求啊
我的结论是,这个 Hook 只适合简单的项目,稍微复杂的项目还是要引入正儿八经的状态库的。
我的结论是,这个 Hook 只适合简单的项目,稍微复杂的项目还是要引入正儿八经的状态库的。
很早期我就有在大大小小的项目使用了,目前没什么问题,甚至有很多好处。这个就是使用很简单,如果项目是需要靠使用门槛来限制全局状态的使用,用别的状态库也是可以的。
用 key 这个方案,设计上就是有缺陷的,例如 https://github.com/alibaba/hooks/issues/1832#issuecomment-1229097767 写的 demo,没有办法解决重复 key 的问题
设计上的问题,需要人为的方式避免(比如警告?),肯定是不合理的,一旦项目规模或者团队规模起来了,就是在给他们埋坑
这个就在你的项目中自己维护吧
useLocalStorage难道大型项目里面不能用吗,用了useLocalStorage就是在埋坑吗
如果 useLocalStorage 用于全局状态,那确实是在埋坑...
你的全局状态概念还是传统的里面乱七八糟放很多东西,这种情况全局状态不好管理,但这个全局状态就只是一个状态了,副作用没那么大。
比如一个暗色主题切换,主题色切换,第一直觉就会让人用这个工具,他们本身就是一个状态而已。
而且这样状态颗粒度低,性能也好优化,避免了传统全局状态里面放的东西太多,带来的不必要的渲染
1、我上面说的是这个 Hook 作为全局状态,设计上的弊端
useGlobalState
需要传入 initialValue
,会导致状态的不可预测结合起来就是 https://github.com/alibaba/hooks/issues/1832#issuecomment-1229097767 这个例子,使用 Foo 组件的时候 Count 是 1,使用 Bar 组件的时候 Count 变成了 2,反而会增加复杂性
2、对于全局状态的数据规模,如果复杂度比较低,比如一个主题色切换,那使用传统的状态管理一样有这些优点 "状态颗粒度低、性能也好优化、避免带来的不必要的渲染"
但是反过来,如果全局状态有一定的复杂度,用 useGlobalState
反而不好管理了
所以,这个 RFC 个人觉得没有必要,先关了。有问题可以继续讨论哈
一般使用都是会二次封装比如例子useGlobalStep,因为没人想重复去写key和初始值还有类型,复杂例子我也写了的useGlobalABC,我个人觉得很多人被redux、dva给教化了,没有需求制造需求,简单的反而是异类了
一般使用都是会二次封装比如例子useGlobalStep,因为没人想重复去写key和初始值还有类型,复杂例子我也写了的useGlobalABC,我个人觉得很多人被redux、dva给教化了,没有需求制造需求,简单的反而是异类了
我现在一直用 hox,很简单的一个状态管理库。
我认为这个 hook 还是挺有意思的,有点类似于 vue 中将 ref 变量放到 composition api 外。 所谓的 key 和 初始值问题,可以稍微改造一下。 让 开发者 不传这个,传一个对象,如果是同一个对象,那么就是同一个全局状态;这样初始值就没有歧义了。state 和 sets 都存储到这个对象里。
改造了一下 demo ,可以参考。https://codesandbox.io/s/dumi-demo-forked-z6j9zh?file=/combination-use.tsx
https://github.com/reactjs/rfcs/pull/224#issuecomment-1678265041 react-use
已经有了。要解决 key
重复,用 Symbo
代替字符串就行了。最大的问题是初始化值,其实加个警告说已经初始化过了也可以。
useGlobalState
React Hook 实现一个全局状态的功能,不同页面不同组件使用同一个状态。Preview →
https://user-images.githubusercontent.com/29084441/186406656-d0f1a7fd-0402-4bf6-ac8c-d16122b5eb24.mp4
Usage
1.先为全局状态设置一个唯一
key
,或者还可以设置一个初始值或者二次封装一个
useGlobalStep
2.在其他组件或者页面引入
useGlobalState
并使用相同的key
或者使用二次封装的
useGlobalStep
API
useGlobalState\<T>(key: string, initState?: T): [T, (state: T) => void]
string
key
any
Demo