前言
项目中遇到的场景: 在文章详情页面,有对作者的关注按钮
之后又点进作者的个人空间还有一个
然后点一下关注
返回详情页面,这个按钮没有更新
问题
同一时间可能存在多个关注按钮,他们都是相同的含义,但每个按钮都创建一个独立的state,这时就会出现这个问题:
缓存没有及时得到更新,含有旧状态的组件()就遗留在了页面上。 所以需要让多个组件使用同一个状态。
当关注按钮点击 切换状态 之后,然而,页面中滞留的其他的 关注按钮应该同时更新。
总之 未响应的根本原因是 本应使用同一state的组件的state割裂开来。
分析
这是一个状态管理的问题,也很好解决
只要将含有同一含义的组件,link到同一个state上就行了。
可以采用
1.寻找他们共同的一个父组件来做状态提升
2.使用redux进行状态管理
3.使用EventEmitter来做消息订阅
因为按钮分散在各个页面当中,属于非父子组件,也是非爷孙组件,所以状态共享做成全局的显然是最明智的。每个按钮的都含有 一个userId,利用userId来区分对应哪一个state是最好的
实现
1.采用第三方 EventEmitter
同名组件 同一内容 同时改变
useEffect(() => {
const callBack = userIdArg => {
if (userIdArg === userId) { //如果是同一userId的其他按钮发生改变,
//我也发生改变
stateChange();
}
};
EventEmitter.addListener('changeState', callBack);
return () => {
EventEmitter.removeListener('changeState', callBack);
};
}, []);
onPress={()=>{
EventEmitter.emit('changeState',userId);
}
}
优点:1.全局 2.方便
缺点:只适用于单个组件,其余使用同一内容的组件需要link到同一个EventEmitter(消息订阅对象)里,这时候有重名的风险。
我认为的同一个组件中共享状态的最优解!!!
2.利用redux 把缓存做成响应式的
同一内容 同时改变
思路是把userInfo都存储到redux里,每个关注按钮根据props里的userId找到对应的redux,如果状态改变,就直接更新redux就行了。
我比较推荐的方案是,使用useReducer + 根部 context.Provider 做一个全局的userInfo的缓存+状态库,关注按钮都link到同一userId的state中,这样保证 同一userId名下的关注按钮都是同步更新的
没有代码
优点:不同组件也可以使用同一内容下的state,且最清楚明朗,通过这个也可以做userInfo的缓存
缺点:有点大材小用,若使用根部Context+useReducer做简单的redux,那么组件树都深入了一层,并且Provider的位置很难找到
在观看ahooks里的 useRequest中我悟了,利用同一request的内容 + key值,来锁定两个组件使用的是同一state就可以了。 不同组件 同一内容 同时改变