【问题标题】:Why a dispatch to a reducer causes all reducers get called?为什么调度到减速器会导致所有减速器被调用?
【发布时间】:2021-01-05 14:13:43
【问题描述】:

在这个github redux example 中,事件ADD_TODO 的调度用于添加任务。在调试过程中,我发现添加一个任务会导致reducers todosvisibilityFilter 都被调用。

如何在添加任务时只调用 todos 减速器而不是 visibilityFilter 减速器。如果我发送了 SET_VISIBILITY_FILTER 类型的事件,还有 visibilityFilter 减速器。

【问题讨论】:

  • 我只是克隆了 repo 并没有修改任何东西。我为SET_VISIBILITY_FILTER 操作和ADD_TODO 添加了一个console.log。当我添加任务时,它不会记录来自SET_VISIBILITY_FILTER reducer 的任何内容
  • 我没有使用控制台日志,而是直接在谷歌chrome调试器中调试。您可以通过 (1) 在 switch 语句之前在两个 reducer 中放置断点 (2) 转到浏览器中的 UI(locahost:3000 如果您运行命令 npm start)并添加任务,例如“测试任务”来重现在编辑框中。您将看到两个减速器都中断了,但只有 todos 减速器中的操作被执行。
  • 不是因为combineReducers() 解析了reducers 并没有实际执行它们吗?

标签: redux react-redux


【解决方案1】:

combineReducers 实用程序有意为每个操作调用所有附加的 reducer 函数,并给它们一个响应的机会。这是因为建议的 Redux reducer 结构是“reducer composition”,其中许多大部分独立的 reducer 函数可以组合成一个结构,并且许多 reducer 函数可能会响应单个操作并更新它们自己的状态切片。

【讨论】:

  • 我担心的是 MapStateToProps 方法,它会被所有容器组件调用。就我而言,我有 5 个容器组件。当一个动作被调度时,它应该只更新一个容器,而不是任何子组件或兄弟组件。我看到所有 5 个容器都调用了 MapStateToProps 函数,并且正在浪费资源。有没有办法可以阻止 MapStateToProps 被执行?
  • 没有。您误解了 mapStateToProps 背后的意图,以及 React-Redux connect() 函数如何使用它。由于 Redux 中只有一个状态树,因此任何调度的操作可能更新了状态的任何部分,并且只有一个订阅通知。因此,connect() 重新运行 所有 订阅的 MSTP 函数,然后对每个函数的结果进行浅层比较,以查看与上次调用相比是否有任何变化。如果 MSTP 的输出相同,则不会重新渲染组件。您希望每次都重新运行 MSTP。
  • 我没有使用Reselect。不过,你所描述的会起作用吗?这不是我在代码中看到的。没有阻止运行 MSTP 功能的逻辑。
  • 感觉就像我们在这里谈论的目的不同。回顾: 1) 使用combineReducers 会自动让所有子减速器有机会响应每个调度的动作,以防他们感兴趣。 2) 使用connect() always 调用every 连接的组件的mapStateToProps 用于every 调度的操作。对于每个 MSTP 调用,connect() 然后将新的 MSTP 返回值与旧的 MSTP 返回值进行比较,如果没有任何更改,则该组件不会重新渲染。为什么要阻止调用 MSTP?这违背了connect() 的目的。
  • 我也很困惑我们是如何从最初的问题“我如何只为特定操作调用特定的减速器”到“我如何让mapStateToProps 不运行”。
【解决方案2】:

正如其他答案中提到的,combineReducers 在调用调度时调用每个reducer。您可以通过使默认情况等于传入的状态参数来避免其他值的变化,因此基本上它们被重新分配了它们的当前值。 例如:

const individualReducer = (state = "initialState", action) => {
    switch(action.type)
    {
        case "ACTION_TYPE":
            return action.payload;
        default:
            return state;
    }
}

export default individualReducer;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-12
    • 2015-01-11
    • 2019-06-03
    • 2016-02-09
    • 1970-01-01
    • 2014-09-20
    • 2021-01-13
    • 2021-10-22
    相关资源
    最近更新 更多