在Redux Reducer中读取Store的初始状态 [英] Read Store's Initial State in Redux Reducer

查看:146
本文介绍了在Redux Reducer中读取Store的初始状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Initial state in a Redux app can be set in two ways:


  • 将其作为第二个参数传递给 createStore docs links

  • 将其作为您的(子)缩减器的第一个参数传递( docs链接

  • pass it as the second argument to createStore (docs link)
  • pass it as the first argument to your (sub-)reducers (docs link)

如果您将初始状态传递到商店,那么如何从商店中读取该状态并进行制作它是你的Redurs中的第一个参数?

If you pass initial state to your store, how do you read that state from the store and make it the first argument in your reducers?

推荐答案


TL; DR



如果没有 combineReducers()或类似的手动代码, initialState 总是胜过<$ c减速器中的$ c> state = ... ,因为传递给reducer 状态 initialState 不是 undefined ,因此在这种情况下不会应用ES6参数语法。

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.

使用 combineReducers()行为更加微妙。那些状态在 initialState 中指定的Reducer将收到 state 。其他减速器将收到 undefined ,因此将回退到 state = ... 他们指定的默认参数。

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.

通常, initialState 胜过reducer指定的状态。这使得Reducer可以将对它们有意义的初始数据指定为默认参数,但是当您从某个持久存储或服务器中保存商店时,还允许加载现有数据(完全或部分)。 strong>

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.

首先让我们考虑一下你有一个减速器的情况。

假设你不使用 combineReducers()

First let's consider a case where you have a single reducer.
Say you don't use combineReducers().

然后你的减速器可能如下所示:

Then your reducer might look like this:

function counter(state = 0, action) {
  switch (action.type) {
  case 'INCREMENT': return state + 1;
  case 'DECREMENT': return state - 1;
  default: return state;
  }
}

现在让我们说你用它创建一个商店。

Now let's say you create a store with it.

import { createStore } from 'redux';
let store = createStore(counter);
console.log(store.getState()); // 0

初始状态为零。为什么?因为 createStore 的第二个参数是 undefined 。这是第一次传递给reducer的状态。当Redux初始化时,它会调度虚拟动作来填充状态。所以你的计数器 reducer被调用时, state 等于 undefined 这就是激活默认参数的情况。因此,现在 0 根据默认值(州= 0 )。将返回此状态( 0 )。

The initial state is zero. Why? Because the second argument to createStore was undefined. This is the state passed to your reducer the first time. When Redux initializes it dispatches a "dummy" action to fill the state. So your counter reducer was called with state equal to undefined. This is exactly the case that "activates" the default argument. Therefore, state is now 0 as per the default state value (state = 0). This state (0) will be returned.

让我们考虑一个不同的场景:

Let's consider a different scenario:

import { createStore } from 'redux';
let store = createStore(counter, 42);
console.log(store.getState()); // 42

为什么 42 ,而不是 0 ,这次?因为 createStore 是以 42 作为第二个参数调用的。此参数变为与$ action一起传递给reducer的状态这次,未定义(它是 42 !),因此ES6默认参数语法无效。 42 42 从reducer返回。

Why is it 42, and not 0, this time? Because createStore was called with 42 as the second argument. This argument becomes the state passed to your reducer along with the dummy action. This time, state is not undefined (it's 42!), so ES6 default argument syntax has no effect. The state is 42, and 42 is returned from the reducer.

现在让我们考虑使用 combineReducers()的情况

你有两个减速器:

Now let's consider a case where you use combineReducers().
You have two reducers:

function a(state = 'lol', action) {
  return state;
}

function b(state = 'wat', action) {
  return state;
}

combineReducers生成的reducer({a,b })看起来像这样:

// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
  return {
    a: a(state.a, action),
    b: b(state.b, action)
  };
}

如果我们调用 createStore 没有 initialState ,它会将初始化为 {} 。因此, state.a state.b 将是 undefined 当它调用 a b reducers时。 a b reducer将收到 undefined 作为他们的 参数,如果他们指定默认的值,那么将返回。这是组合的reducer在第一次调用时返回 {a:'lol',b:'wat'} 状态对象的方式。

If we call createStore without the initialState, it's going to initialize the state to {}. Therefore, state.a and state.b will be undefined by the time it calls a and b reducers. Both a and b reducers will receive undefined as their state arguments, and if they specify default state values, those will be returned. This is how the combined reducer returns a { a: 'lol', b: 'wat' } state object on the first invocation.

import { createStore } from 'redux';
let store = createStore(combined);
console.log(store.getState()); // { a: 'lol', b: 'wat' }

让我们考虑一个不同的场景:

Let's consider a different scenario:

import { createStore } from 'redux';
let store = createStore(combined, { a: 'horse' });
console.log(store.getState()); // { a: 'horse', b: 'wat' }

现在我指定了 initialState 作为 createStore()的参数。从合并的reducer 返回的状态组合我为 a reducer指定的初始状态与'wat'默认参数指定 b reducer选择自己。

Now I specified the initialState as the argument to createStore(). The state returned from the combined reducer combines the initial state I specified for the a reducer with the 'wat' default argument specified that b reducer chose itself.

让我们回想一下合并的reducer的作用:

Let's recall what the combined reducer does:

// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
  return {
    a: a(state.a, action),
    b: b(state.b, action)
  };
}

在这种情况下,已指定,因此它不会回退到 {} 。这是 a 字段等于'horse'的对象,但没有 b 字段。这就是为什么 a 减速器收到'horse'作为其并乐意将其退回,但 b reducer收到 undefined 作为其并因此返回其默认的想法(在我们的示例中,'wat')。这就是我们如何得到 {a:'马',b:'wat'} 作为回报。

In this case, state was specified so it didn't fall back to {}. It was an object with a field equal to 'horse', but without the b field. This is why the a reducer received 'horse' as its state and gladly returned it, but the b reducer received undefined as its state and thus returned its idea of the default state (in our example, 'wat'). This is how we get { a: 'horse', b: 'wat' } in return.

总结一下,如果你坚持使用Redux约定并在使用 undefined 调用它们时从reducers返回初始状态 state 参数(最简单的实现方法是指定 state ES6默认参数值),你要去为组合减速器提供一个很好的有用行为。 他们会更喜欢传递给 createStore()函数的 initialState 对象中的相应值,但是如果你没有传递任何,或者如果没有设置相应的字段,则选择reducer指定的默认 state 参数。这种方法效果很好,因为它提供现有数据的初始化和水合作用,但如果未保留数据,则允许各个reducers重置其状态。当然,您可以递归地应用此模式,因为您可以在许多级别上使用 combineReducers(),甚至可以通过调用reducers并为其提供相关的部分来手动编写Reducer树。

To sum this up, if you stick to Redux conventions and return the initial state from reducers when they're called with undefined as the state argument (the easiest way to implement this is to specify the state ES6 default argument value), you're going to have a nice useful behavior for combined reducers. They will prefer the corresponding value in the initialState object you pass to the createStore() function, but if you didn't pass any, or if the corresponding field is not set, the default state argument specified by the reducer is chosen instead. This approach works well because it provides both initialization and hydration of existing data, but lets individual reducers reset their state if their data was not preserved. Of course you can apply this pattern recursively, as you can use combineReducers() on many levels, or even compose reducers manually by calling reducers and giving them the relevant part of the state tree.

这篇关于在Redux Reducer中读取Store的初始状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆