【发布时间】:2021-11-08 06:42:00
【问题描述】:
总结
在 reducer 中更新缓存好不好?我的意思是,是否可以在我的前端的每个部分(组件、屏幕、挂钩、帮助程序...)中更新缓存,还是应该将此行为委托给系统的特定部分?
简介
在我的应用中,每个用户都有一个字段“totalFollowers”。
我将每个用户的数据存储在 React Context 的状态中。为了根据之前的状态执行复杂而纯粹的更新,我使用了 reducer。
此外,我还实现了内存中的 LRU 缓存,只是为了避免不必要的数据库请求并提高用户体验/性能。在这个缓存中,我存储了一些数据,这些数据也包含在我谈到的 React 上下文中......所以,在双方,数据必须相等。
当当前用户关注他时,我正在更新特定用户的 totalFollowers 字段,在我的减速器中,我有以下内容:
export default (otherUsers, action) => {
switch (action.type) {
case "follow-user": {
const { userId, isFollowing } = action;
const prevUserData = otherUsers.get(userId);
return new Map([
...otherUsers,
[
userId,
{
...prevUserData,
totalFollowers: prevUserData.totalFollowers + (isFollowing ? 1 : -1)
]
]
);
}
...
}
}
问题
正如我之前所说...我的缓存有一些数据也包含在上下文中(使用我描述的 reducer),“totalFollowers”就是其中之一。
如果我的 reducer 让我能够以本机/原子方式访问状态,我认为在其中更新我的缓存是个好主意。但是,我读过减速器的唯一目的是更新状态......我很害怕,因为我更新减速器内部缓存的想法可能是一种反模式(避免纯函数内部的副作用)
你怎么看?在 reducer 中执行缓存更新是否“正确”?
import { usersCache } from "../../services/firebase/api/users"
export default (otherUsers, action) => {
switch (action.type) {
case "follow-user": {
const { userId, isFollowing } = action;
const prevUserData = otherUsers.get(userId);
const newTotalFollowers = prevUserData.totalFollowers + (isFollowing ? 1 : -1);
usersCache.updateUser(userId, { totalFollowers: newTotalFollowers }); // merge update
return new Map([
...otherUsers,
[
userId,
{
...prevUserData,
totalFollowers: newTotalFollowers
]
]
);
}
...
}
}
【问题讨论】:
-
@DrewReese 认为当组件卸载或用户会话关闭时状态被破坏(我的导航中的身份验证保护路由)。我正在使用该缓存来避免发出数据库请求,而不是在 GUI 中呈现内容,只是为了返回缓存的数据。 redux 能解决这个问题吗?
-
我的意思是,IMO 您正在尝试优化代码的错误部分。是的,Redux 是一个全局状态管理工具,使用 reducer,所以如果你已经在使用
useReducer钩子会很熟悉,它是使用 React 上下文 API 构建的,并且可以很好地扩展。 Redux-toolkit 是对 redux 和 react-redux 的抽象,包括缓存对后端系统的查询 (redux-toolkit.js.org/rtk-query/overview)。 -
@DrewReese 非常感谢您的帮助,我会尽快迁移到 Redux。但是,为什么您认为不需要缓存用户数据?在我的用例中,我只是保存最新的数据(可以来自用户配置文件中的下拉刷新,并且可以在按下典型的关注按钮时进行修改(totalFollowers 字段))。我以前认为我的上下文可能是“缓存”,但是不可能在我的 api 模块中使用 React 上下文......并且当用户退出时它将被卸载,我认为记忆模式可能很好.
-
在上下文中同步路由。在缓存中也有记忆结果然后上下文被卸载(用户退出)。
标签: javascript reactjs react-native caching