【React】关于状态共享+缓存更新的一点思考

268 阅读3分钟

前言

项目中遇到的场景: 在文章详情页面,有对作者的关注按钮

image.png

之后又点进作者的个人空间还有一个 image.png

然后点一下关注

image.png

返回详情页面,这个按钮没有更新

image.png

问题

同一时间可能存在多个关注按钮,他们都是相同的含义,但每个按钮都创建一个独立的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就可以了。 不同组件 同一内容 同时改变

image.png