Redux:将部分状态作为卸载组件丢弃?

时间:2016-04-12 20:19:47

标签: reactjs redux

我目前正在使用react,redux和react-router编写应用程序。

应用程序的许多路径(或子路由)都会使用最终合并的reducer来填充redux存储的状态。

但通常情况下,由路由组件管理的状态部分特定于此组件,并且"可以被删除"卸载组件后。

我担心当用户浏览不同的屏幕时,他会用未使用的数据填充状态并使整个应用程序膨胀。所以我正在思考一种方法来放弃未使用的部分状态。

让我们采用一个CRUD应用程序,用于多个不同的实体(问题,帖子,图像......)。虽然我列出了问题,但可能没有必要在州内设置帖子,反之亦然。 我应该在转换到问题列表时删除帖子列表吗?

这是一种不好的做法吗?有一个很好的方法来做到这一点?你觉得怎么样?

3 个答案:

答案 0 :(得分:13)

除非您处理成千上万条记录,否则可能不值得付出代价并使代码复杂化。您确定这对您的应用来说是一个真正的问题吗?保持旧状态实际上很方便,例如用于即时“后退”按钮。

如果您对此感到强烈,您可以在卸载某些组件或路由更改时发送清理操作。但是我认为在绝大多数应用程序中这是不必要的,只要你记得在安装后检查任何新项目,保留缓存可能更好。

答案 1 :(得分:4)

如果您的数据已加载到详细信息组件(不是)中,我认为可以恢复状态。

因为详细状态组件实际上不会被“缓存”,所以即使您切换回 show 相同的资源,也会再次下载数据。如果您要显示不同的资源,上次访问资源的剩余状态将保持不变,直到下载当前资源的数据为止,并将连接到用户。

其中一种方法是定义一个动作/缩减器,以便在 detail 组件卸载时恢复状态。

另一种方法是在路线改变时恢复状态:

import { LOCATION_CHANGE } from 'react-router-redux'
import * as types from 'constants/ActionTypes'

const initialState = {}

export default function show(state = initialState, action) {

  switch (action.type) {

    case types.LOGOUT:
    case LOCATION_CHANGE:
      return initialState

    case types.SHOW_SUCCESS:
      return action.payload

    default:
      return state
  }
}

答案 2 :(得分:2)

@Dan Abramov不仅不是必需的,而且还可能导致难以跟踪错误。我们已经体验到,由于componentWillUnmount()是异步的,因此当您从该视图直接转到依赖于reducer的此部分的另一个视图时,在分派操作以清除componentWillUnmount()内部的某些reducer时,可能会导致错误。

例如:

假设您具有以下商店状态形状:

const state = {
    list: ["thing"]
}

然后想象一下我在名为Things的视图中使用此状态

然后想象一下,我意识到在其他10个视图中的9个中我没有使用state.list,因此我决定要防止“膨胀”或“内存泄漏”,并且我采取了一项措施来清除本节组件中的WillUnmount in Things状态中的状态

您希望事件的顺序始终是:

  1. 卸载物品
  2. 调度操作以清除state.list
  3. 然后安装下一个视图
  4. 然后在10个视图中的1个中重新填充state.list(如果在此视图中需要的话)

但是,这不是顺序。有时反而会是:

  1. 卸载事物并直接转到需要state.list的另一个视图
  2. 立即安装下一个视图。我们的视图确实需要state.list,因此我们分派了此操作。或者,因为state.list已经存在,所以我们不调度获取操作,因为我们已经拥有它。
  3. 稍后,componentWillUnmount成功调度了CLEAR操作
  4. 即使您不想这样做,也无意中清除了该视图中的state.list。当然,由于我们已@connected,所以屏幕变黑了!

也就是说,即使Redux是同步的,componentWillUnmount也不是同步的,因此不能保证在其中调度的任何操作都将按您期望的顺序发生。在任何情况下,如果您确实直接转到确实要该状态部分的另一个视图,这都是一个问题。

解决此问题的一种方法是在componentWillUnmount中有条件地说:“如果出于以下原因我要离开(取消安装)此视图,则仅分派CLEAR操作...不,当我进入其他视图时确实依赖于本节内容,例如,您可以通过在localState中拥有一个名为shouldIClearList:之类的属性来进行此操作,并且默认情况下为true,除非我单击名为goToMyOtherViewThatNeedsList的按钮。在很多情况下,如果到另一个需要列表的视图的链接位于一个完全不同的顶级父组件(如Navbar)中,则很复杂,因此,要尝试转到的视图是否是此“问题视图”并不容易被您的子事物组件“识别”。

我实际上认为“膨胀”是一个有效的想法,并且在卸载时清除redux而不遇到类似问题的最佳方法将不胜感激。我能看到的唯一解决方案是永远不要清除componentWillUnmount内部的reducer。太危险了。或者,如果绝对需要,请确保您的应用程序中绝对没有办法直接从此视图转到需要此状态部分的另一个视图(在大型应用程序中无需某种操作就很难做到)公司所有软件团队之间共享的文档集)。