javascript - 在 Redux Reducer 中读取 Store 的初始状态

标签 javascript reactjs redux

Redux 应用程序中的初始状态可以通过两种方式设置:

  • 将它作为第二个参数传递给 createStore ( docs link )
  • 将它作为第一个参数传递给你的(子)reducers(docs link)

  • 如果您将初始状态传递给您的商店,您如何从商店中读取该状态并将其作为 reducer 中的第一个参数?

    最佳答案

    TL;DR

    Without combineReducers() or similar manual code, initialState always wins over state = ... in the reducer because the state passed to the reducer is initialState and is not undefined, so the ES6 argument syntax doesn't get applied in this case.

    With combineReducers() the behavior is more nuanced. Those reducers whose state is specified in initialState will receive that state. Other reducers will receive undefined and because of that will fall back to the state = ... default argument they specify.

    In general, initialState wins over the state specified by the reducer. This lets reducers specify initial data that makes sense to them as default arguments, but also allows loading existing data (fully or partially) when you're hydrating the store from some persistent storage or the server.


    首先让我们考虑一个只有一个 reducer 的情况。
    说你不使用 combineReducers() .
    然后你的 reducer 可能看起来像这样:
    function counter(state = 0, action) {
      switch (action.type) {
      case 'INCREMENT': return state + 1;
      case 'DECREMENT': return state - 1;
      default: return state;
      }
    }
    
    现在假设您用它创建了一个商店。
    import { createStore } from 'redux';
    let store = createStore(counter);
    console.log(store.getState()); // 0
    
    初始状态为零。为什么?因为 createStore 的第二个参数是 undefined .这是state第一次传递给你的 reducer 。当 Redux 初始化时,它会分派(dispatch)一个“虚拟” Action 来填充状态。所以你的counter使用 state 调用 reducer 等于 undefined . 这正是“激活”默认参数的情况。 因此,state现在是 0根据默认 state值(state = 0)。将返回此状态 (0)。
    让我们考虑一个不同的场景:
    import { createStore } from 'redux';
    let store = createStore(counter, 42);
    console.log(store.getState()); // 42
    
    为什么是42 , 而不是 0 , 这次?因为createStore被调用 42作为第二个论点。该参数变为 state与虚拟 Action 一起传递给您的 reducer 。 这一次,state不是未定义的(它是 42 !),因此 ES6 默认参数语法无效。 state42 , 和 42从 reducer 返回。

    现在让我们考虑一个使用 combineReducers() 的情况。 .
    你有两个 reducer :
    function a(state = 'lol', action) {
      return state;
    }
    
    function b(state = 'wat', action) {
      return state;
    }
    
    combineReducers({ a, b })生成的reducer看起来像这样:
    // const combined = combineReducers({ a, b })
    function combined(state = {}, action) {
      return {
        a: a(state.a, action),
        b: b(state.b, action)
      };
    }
    
    如果我们调用 createStore没有 initialState ,它将初始化 state{} .因此,state.astate.b将是 undefined当它调用 a 时和 b reducer 。 两个ab reducer 将收到 undefined作为他们的state参数,如果他们指定默认 state值,那些将被返回。 这就是组合 reducer 返回 { a: 'lol', b: 'wat' } 的方式。第一次调用时的状态对象。
    import { createStore } from 'redux';
    let store = createStore(combined);
    console.log(store.getState()); // { a: 'lol', b: 'wat' }
    
    让我们考虑一个不同的场景:
    import { createStore } from 'redux';
    let store = createStore(combined, { a: 'horse' });
    console.log(store.getState()); // { a: 'horse', b: 'wat' }
    
    现在我指定了 initialState作为 createStore() 的参数.从组合 reducer 返回的状态结合了我为 a 指定的初始状态带 'wat' 的 reducer 默认参数指定 b reducer 选择了自己。
    让我们回顾一下组合 reducer 的作用:
    // const combined = combineReducers({ a, b })
    function combined(state = {}, action) {
      return {
        a: a(state.a, action),
        b: b(state.b, action)
      };
    }
    
    在这种情况下,state已指定,因此它不会回退到 {} .它是一个带有 a 的对象字段等于 'horse' ,但没有 b field 。这就是为什么 a收到 reducer 'horse'作为它的state并高兴地退回了它,但是 b收到 reducer undefined作为它的state并因此返回了默认 state 的想法(在我们的示例中,'wat')。这就是我们得到 { a: 'horse', b: 'wat' } 的方式作为返回。

    综上所述,如果你坚持 Redux 约定并在使用 undefined 调用 reducer 时从 reducer 返回初始状态。作为 state参数(实现这一点的最简单方法是指定 state ES6 默认参数值),您将对组合 reducer 有一个很好的有用行为。 他们会更喜欢 initialState 中的相应值。传递给 createStore() 的对象函数,但是如果你没有传递任何,或者没有设置对应的字段,默认state而是选择由 reducer 指定的参数。 这种方法效果很好,因为它提供了现有数据的初始化和水合,但是如果他们的数据没有被保留,它会让单个 reducer 重置他们的状态。当然,您可以递归地应用此模式,因为您可以使用 combineReducers()在许多层面上,甚至通过调用 reducer 并为它们提供状态树的相关部分来手动组合 reducer。

    关于javascript - 在 Redux Reducer 中读取 Store 的初始状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33749759/

    相关文章:

    javascript - React-Redux:映射对象数组并从每个对象初始化一个组件

    java - 在 Chrome 浏览器上删除 NPAPI 后替代 Jzebra/QZ Java Raw Print Plugin

    javascript - Node.js 和 JSON : Accessing object properties

    c# - 解释 Asp.net 中的 slider 代码

    reactjs - react 状态返回未定义

    javascript - 如何在嵌套数组中使用reducer

    reactjs - 在 React 组件中本地操作 redux 状态的最佳实践

    reactjs - 如何使用 Redux Provider 包装导航堆栈(createSwitchNavigator)?

    javascript - 对象数组,按父对象分组

    javascript - 从数据中 react 表删除行而不刷新