React Redux combineReducers 函数在导出时调用我的减速器 2 次,并在 createStore 函数中额外调用一次
React Redux combineReducers function calls my reducers 2 times when its exported and an additional time in the createStore function
我是 Redux 的新手,我想了解为什么 combineReducers 函数会调用 reducer 两次。
我的 reducer/index.js 看起来像这样
import {combineReducers} from "redux"
const AReducer = (state = "A", action) =>{
console.log("In A reducer")
switch (action.type){
case "Alpha":
return state + action.payload
default:
return state
}
}
const BReducer = (state = "B", action) =>{
console.log("In B reducer")
switch(action.type)
{
case "Beta":
return state + action.payload
default:
return state
}
}
const allReducers = combineReducers({
A : AReducer,
B : BReducer
})
export default allReducers
我的 store/index.js 看起来像这样
import {createStore} from "redux";
import allReducers from "../Reducer"
const store = createStore(allReducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default store
并且控制台日志显示了这个
index.js:4 In A reducer
index.js:4 In A reducer
index.js:15 In B reducer
index.js:15 In B reducer
index.js:4 In A reducer
index.js:15 In B reducer
我只想了解为什么会这样。我想更好地了解后台发生的事情
首先,让我们打印 action
.
import { combineReducers, createStore } from 'redux';
const AReducer = (state = 'A', action) => {
console.log('In A reducer, action: ', action);
switch (action.type) {
case 'Alpha':
return state + action.payload;
default:
return state;
}
};
const BReducer = (state = 'B', action) => {
console.log('In B reducer, action: ', action);
switch (action.type) {
case 'Beta':
return state + action.payload;
default:
return state;
}
};
const allReducers = combineReducers({
A: AReducer,
B: BReducer,
});
const store = createStore(allReducers);
日志:
In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
In A reducer, action: { type: '@@redux/PROBE_UNKNOWN_ACTIONn.x.t.b.s.j' }
In B reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
In B reducer, action: { type: '@@redux/PROBE_UNKNOWN_ACTIONu.8.f.5.c.h' }
In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
In B reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
说明
我用AReducer
的日志来说明,Breducer
也是一样。
combineReducers
函数在内部调用 assertReducerShape() 函数。
assertReducerShape()
函数将使用 init action 调用在 combineReducers
函数中传递的每个缩减器,以检查缩减器是否具有有效的 returned 值。 In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
日志就是这样来的
并且,它还会调用每个带有 unknown actions 的减速器来检查减速器 return 是否为任何未知操作的当前状态,除非它是 undefined
。 In A reducer, action: { type: '@@redux/PROBE_UNKNOWN_ACTIONn.x.t.b.s.j' }
日志就是这样来的
调用createStore
函数时,会dispatch init action. So that every reducer returns their initial state. This effectively populates the initial state tree. This is how In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
log come. This process is mentioned in the documentation, See tips.
另请查看 utils/actionTypes 文件中的 INIT
和 PROBE_UNKNOWN_ACTION
操作类型。
const randomString = () =>
Math.random().toString(36).substring(7).split('').join('.')
const ActionTypes = {
INIT: `@@redux/INIT${/* #__PURE__ */ randomString()}`,
REPLACE: `@@redux/REPLACE${/* #__PURE__ */ randomString()}`,
PROBE_UNKNOWN_ACTION: () => `@@redux/PROBE_UNKNOWN_ACTION${randomString()}`
}
这些action类型是private的,redux内部使用,你不需要处理。你会在 redux dev tools 中看到 dispatched INIT
action,不要惊讶。
我是 Redux 的新手,我想了解为什么 combineReducers 函数会调用 reducer 两次。
我的 reducer/index.js 看起来像这样
import {combineReducers} from "redux"
const AReducer = (state = "A", action) =>{
console.log("In A reducer")
switch (action.type){
case "Alpha":
return state + action.payload
default:
return state
}
}
const BReducer = (state = "B", action) =>{
console.log("In B reducer")
switch(action.type)
{
case "Beta":
return state + action.payload
default:
return state
}
}
const allReducers = combineReducers({
A : AReducer,
B : BReducer
})
export default allReducers
我的 store/index.js 看起来像这样
import {createStore} from "redux";
import allReducers from "../Reducer"
const store = createStore(allReducers,
window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__()
)
export default store
并且控制台日志显示了这个
index.js:4 In A reducer
index.js:4 In A reducer
index.js:15 In B reducer
index.js:15 In B reducer
index.js:4 In A reducer
index.js:15 In B reducer
我只想了解为什么会这样。我想更好地了解后台发生的事情
首先,让我们打印 action
.
import { combineReducers, createStore } from 'redux';
const AReducer = (state = 'A', action) => {
console.log('In A reducer, action: ', action);
switch (action.type) {
case 'Alpha':
return state + action.payload;
default:
return state;
}
};
const BReducer = (state = 'B', action) => {
console.log('In B reducer, action: ', action);
switch (action.type) {
case 'Beta':
return state + action.payload;
default:
return state;
}
};
const allReducers = combineReducers({
A: AReducer,
B: BReducer,
});
const store = createStore(allReducers);
日志:
In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
In A reducer, action: { type: '@@redux/PROBE_UNKNOWN_ACTIONn.x.t.b.s.j' }
In B reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
In B reducer, action: { type: '@@redux/PROBE_UNKNOWN_ACTIONu.8.f.5.c.h' }
In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
In B reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
说明
我用AReducer
的日志来说明,Breducer
也是一样。
combineReducers
函数在内部调用 assertReducerShape() 函数。
assertReducerShape()
函数将使用 init action 调用在 combineReducers
函数中传递的每个缩减器,以检查缩减器是否具有有效的 returned 值。 In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
日志就是这样来的
并且,它还会调用每个带有 unknown actions 的减速器来检查减速器 return 是否为任何未知操作的当前状态,除非它是 undefined
。 In A reducer, action: { type: '@@redux/PROBE_UNKNOWN_ACTIONn.x.t.b.s.j' }
日志就是这样来的
调用createStore
函数时,会dispatch init action. So that every reducer returns their initial state. This effectively populates the initial state tree. This is how In A reducer, action: { type: '@@redux/INIT3.j.l.q.g.r' }
log come. This process is mentioned in the documentation, See tips.
另请查看 utils/actionTypes 文件中的 INIT
和 PROBE_UNKNOWN_ACTION
操作类型。
const randomString = () =>
Math.random().toString(36).substring(7).split('').join('.')
const ActionTypes = {
INIT: `@@redux/INIT${/* #__PURE__ */ randomString()}`,
REPLACE: `@@redux/REPLACE${/* #__PURE__ */ randomString()}`,
PROBE_UNKNOWN_ACTION: () => `@@redux/PROBE_UNKNOWN_ACTION${randomString()}`
}
这些action类型是private的,redux内部使用,你不需要处理。你会在 redux dev tools 中看到 dispatched INIT
action,不要惊讶。