TL;博士
如果没有
combineReducers()
或类似的手动代码,initialState
在reducer中总是胜过state = ...
,因为state
传递给reducer isinitialState
和is notundefined
,所以ES6参数语法不适用于这种情况.
combineReducers()
岁时,行为更加微妙.initialState
中规定状态的减速器将收到state
.其他减速器将接收undefined
and because of that,并返回到它们指定的默认参数state = ...
.In general, 100 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.
First let's consider a case where you have a single reducer.
Say you don't use combineReducers()
.
那么你的减速器可能是这样的:
function counter(state = 0, action) {
switch (action.type) {
case 'INCREMENT': return state + 1;
case 'DECREMENT': return state - 1;
default: return state;
}
}
现在假设你用它创建了一个store .
import { createStore } from 'redux';
let store = createStore(counter);
console.log(store.getState()); // 0
初始状态为零.为什么?因为createStore
的第二个参数是undefined
.这是第一次传递给减速器的state
.当Redux初始化时,它会发送一个"虚拟"操作来填充状态.所以你的counter
减速机被称为state
等于undefined
.This is exactly the case that “activates” the default argument.因此,根据默认的state
值(state = 0
),state
现在是0
.将返回此状态(0
).
让我们考虑另一种情况:
import { createStore } from 'redux';
let store = createStore(counter, 42);
console.log(store.getState()); // 42
为什么这次是42
,而不是0
?因为createStore
是以42
作为第二个参数调用的.此参数将与伪操作一起传递给减速机.This time, 104 is not undefined (it's 100!), so ES6 default argument syntax has no effect. state
为42
,42
从减速器返回.
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({ a, b })
生成的减速器如下所示:
// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
return {
a: a(state.a, action),
b: b(state.b, action)
};
}
如果我们在没有initialState
的情况下调用createStore
,它将初始化state
到{}
.因此,当它调用a
和b
减速机时,state.a
和state.b
将是undefined
.Both 107 and 108 reducers will receive 106 as their 102 arguments, and if they specify default 102 values, those will be returned.这就是组合减速器在第一次调用时返回{ 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()
的参数.从组合减速器combines返回的状态是我为a
减速器指定的初始状态,'wat'
默认参数指定b
减速器自行 Select .
让我们回忆一下组合减速器的功能:
// const combined = combineReducers({ a, b })
function combined(state = {}, action) {
return {
a: a(state.a, action),
b: b(state.b, action)
};
}
在本例中,指定了state
,因此它不会回落到{}
.这是一个a
场等于'horse'
场的物体,但没有b
场.这就是为什么a
减速机收到'horse'
作为其state
并愉快地返回它,但b
减速机收到undefined
作为其state
,因此返回默认state
中的its idea(在我们的示例中为'wat'
).这就是我们得到回报的方式.
综上所述,如果您坚持Redux约定,并在使用undefined
作为state
参数调用减缩器时从减缩器返回初始状态(实现这一点的最简单方法是指定state
ES6默认参数值),那么对于组合减缩器,您将有一个非常有用的行为.They will prefer the corresponding value in the 103 object you pass to the 104 function, but if you didn't pass any, or if the corresponding field is not set, the default 101 argument specified by the reducer is chosen instead.这种方法工作得很好,因为它提供了现有数据的初始化和水合作用,但如果数据未被保留,则允许单个还原程序重置其状态.当然,您可以递归地应用此模式,因为您可以在许多级别上使用combineReducers()
,甚至可以通过调用reducer并为它们提供状态树的相关部分来手动编写reducer.