首页 文章

Redux:将部分状态作为卸载组件删除?

提问于
浏览
8

我目前正在编写一个带有react,redux和react-router的应用程序 .

应用程序的许多路径(或子路由)填充了redux存储的状态,最终将自己的reducers组合在一起 .

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

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

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

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

3 回答

  • 3

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

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

  • 9

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

    因为详细信息组件的状态赢得了't actually be ' cached',此外,即使您切换回显示相同的资源,也会再次下载数据 . 如果您要显示不同的资源,则上次访问资源的剩余状态将保持不变,直到下载当前资源的数据,并且将连接到用户 .

    其中一种方法是定义一个action / reducer,以在详细信息组件要卸载时恢复状态 .

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

    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
      }
    }
    
  • 1

    @Dan Abramov不仅没有必要,而且还可能导致难以追踪错误 . 我们经历过这一点,因为componentWillUnmount()是异步的,当调度一个动作来清除componentWillUnmount()内部的某个reducer时,当你从这个视图直接转到另一个依赖reducer这一部分的视图时,会导致错误 .

    例如:

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

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

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

    然后想象一下,我意识到在我的其他10个视图中有9个我没有使用state.list,所以我决定我想防止“膨胀”或“内存泄漏”,我做了一个动作来清除我的状态的这一部分在thingWillUnmount in Things中

    您会期望事件序列始终是:

    • 卸下东西

    • 调度动作以清除state.list

    • 然后挂载下一个视图

    • 然后在10个视图中的1个中重新填充state.list如果您在此视图中需要它

    但是,这不是序列 . 有时它会改为:

    • 卸载事物并直接转到需要state.list的另一个视图

    • 立即安装下一个视图 . 我们的观点需要state.list,所以我们发出这个动作 . 或者因为state.list已经存在,所以我们不会调度获取操作,因为我们已经拥有了它 .

    • 稍后,componentWillUnmount成功调度CLEAR操作

    • 即使您不想这样,您也无意中清除了此视图中的state.list . 当然,因为我们是@connected我们的屏幕空白!

    也就是说,即使Redux是同步componentWillUnmount也不是同步的,因此无法保证在其中发送的任何操作按照您想要的顺序发生 . 在任何边缘情况下,这是一个问题,在这种情况下,您实际上直接进入另一个需要该状态部分的视图 .

    解决这个问题的一种方法是在componentWillUnmount中设置一个条件,它说“只有在我离开这个视图时才调度CLEAR操作(卸载它),原因如下......”当我继续执行此依赖的其他视图时这个状态部分 . 你可以这样做,例如,在localState中有一个名为shouldIClearList:的属性,默认情况下是真的,除非我点击调用的按钮,goToMyOtherViewThatNeedsList . 但是,在许多情况下,这会增加不必要的复杂性,其中需要列表的其他视图的链接位于完全不同的顶级父组件(如Navbar)中,因此,无论您尝试查看的视图是否“有问题”查看“不容易”知道你的孩子的东西组件 .

    我实际上认为“膨胀”的想法是有效的,并且在没有遇到像这样的问题的情况下清除redux的最佳方法将非常感激 . 我可以看到的唯一解决方案是不要清除componentWillUnmount中的reducer . 太危险了 . 或者,如果你真的必须这样做,确保你的应用程序绝对没有办法从这个视图直接转到另一个需要这个状态部分的视图(在一个巨大的应用程序中很难做到而不必有一些在公司的所有软件团队共享的文档) .

相关问题