React/Redux reducer 在初始化期间返回未定义



我正在做我的第一个React/Redux项目。一切都很顺利,然后我尝试创建一个新的减速器。我认为这是一个非常简单的,但是当我加载页面时,我收到一个错误"Reducer X 在初始化期间返回未定义"。跟踪表明这发生在 combineReducers() 中。我发现了几个类似的问题,但它们并没有解决问题。

关于这个问题:为什么我得到"减速器 [...]在初始化期间返回未定义",尽管向 createStore() 提供了初始状态?

问题是他们在createStore()中使用了initialState,而我没有这样做。

关于这个问题:为什么我的 Redux 化简器认为我的状态是未定义的?

问题是我有的化简器中缺少默认返回值。

我的减速器代码如下。我一开始有一个 console.log(),根本没有被调用。

减速器/reducer_which_sorter.js

import { SORT_CAMPERS } from '../actions/index';
export default function(state = null, action) {
console.log("action is", action);
switch(action.which) {
case 'recent':
case 'alltime':
return action.which;
break;
default:
return state;
}
return state;
}

减速器/索引器.js

import { combineReducers } from 'redux';
import Campers from './reducer_camper_list';
import ActiveSorter from './reducer_which_sorter';
const rootReducer = combineReducers({
campers: Campers,
activeSorter: ActiveSorter
});
export default rootReducer;

一切都编译得很好。没有来自 webpack 的错误。我已经检查了两次,三次和四次检查了我的文件路径。我没有看到任何错别字。谁能看到我在这里缺少的东西?

Redux 的要求是在操作上使用type属性,而不是像您在示例中所做的那样使用which属性。由于未调用控制台.log检查,因此问题可能出在您的其他化简器上(未显示在您的问题中)。

这很重要的原因是combineReducers使用特殊的 INIT 操作类型调用您的化简器函数:

const initialState = reducer(undefined, { type: ActionTypes.INIT })

来源: https://github.com/reactjs/redux/blob/master/src/combineReducers.js

你的函数,因为它打开了"action.which"而不是"action.type",所以除了未定义之外,无法返回任何内容。

我在开头有一个 console.log(),它根本没有被调用。

这很奇怪,因为 reducer 函数必须至少被调用一次@@INIT动作。

尝试测试是否调用了您的rootReducer。将其更改为:

const rootReducer = (state = {}, action) => {
console.log('Test if rootReducer is ever called')
return {
campers: Campers(state.campers, action),
activeSorter: ActiveSorter(state.activeSorter, action)
}
}

如果没有调用它,那么问题出在更高的地方,而不是化简器本身。

当您的return语句未返回有效对象时,将发生此错误,当您看到此错误时,请始终检查化简器返回的内容。

一个更有趣的场景,我正在创建一个基本的 redux 应用程序,并遇到了同样的错误,在我的情况下,我只是返回一个对象数组并得到相同的错误,一切都很好,我把头撞在墙上,最后发现这是由于一个非常非常基本的JavaScript 错误。

return语句检查同一行中的值,并且不考虑下一行。

export default function(){
return     // '[' should be here not in the next line ** basic mistake****
[
{
id: 1,
name: "sachin",
centuries: "100",
country: "India"
},
{
id: 2,
name: "ganguly",
centuries: "42",
country: "India"
},
{
id:3,
name: "dravid",
centuries: "40",
country: "India"
}
]
}

由于javascript返回未定义,combineReducers函数没有接收预期的对象,而是未定义。

确保您有正确的return语句

将化简器放在一起时,在 switch 语句中,您将从操作创建者type属性传递一个action.type。操作创建器中没有which属性可以传递给化简器。

请记住,动作创建者总是将普通的 JavaScript 动作对象传递给化简器。即使它是一个由中间件(如 Redux-Thunk)接收的函数,该中间件最终也会将动作创建者函数修改为要发送到所有化简器的动作对象。

此外,您的案例必须是操作类型本身的值。因此,假设您的操作创建者是异步的,它正在从某个终端节点获取数据,如下所示:

export const allTime = () => async dispatch => {
const response = await someEndPoint.get("/all");
dispatch({ type: 'ALL_TIME', payload: response })
};

除了在 actionstype属性中传递开关之外,大小写必须是该type属性的值,在此示例中'ALL_TIME'并且您想要返回操作创建者的有效负载,如果您告诉我payload属性正在返回which,那么上面的内容将如下所示:

export const allTime = () => async dispatch => {
const which = await someEndPoint.get("/all");
dispatch({ type: 'ALL_TIME', payload: which })
};

否则,您很可能会返回payload: response

所以代替:

export default function(state = null, action) {
console.log("action is", action);
switch(action.which) {
case 'recent':
case 'alltime':
return action.which;
break;
default:
return state;
}
return state;
}

尝试:

export default function(state = null, action) {
console.log("action is", action);
switch(action.type) {
case 'ALL_TIME':
return action.response;
default:
return state;
}
};

看看上面的重构为你做了什么,我相信如果不解决错误,它会让你更接近你的目标。如果你需要重新开始,只要记住JavaScript的规则,一个函数必须始终return一些值,所以你可能需要回到:

export default () => {
return 123;
};

如果您实现这一点,您的错误消息肯定会消失,您可以利用这段时间在SO上考虑问题的答案,并从中省出解决方案。哎呀,你甚至可以实现:

export default () => {
return ‘howdy’;
};

您可以返回一个空数组:

export default () => {
return [];
};

您可以返回一个对象:

export default () => {
return {};
};

您甚至可以像这样返回 null 的值:

export default () => {
return null;
};

您的错误消息将消失。问题现在出在你的逻辑上,相当于这样做:

export default () => {
return undefined;
}

这在减速器的世界里是不可接受的。

您会看到错误显示初始化期间返回未定义。因此,当 Redux 首次启动时,它将运行一次每个化简器。

因此,这意味着第一次运行化简器时,它返回的值为 undefined,您的化简器永远不会返回 undefined,无论是在初始化时还是在将来某个时间点调度操作时。

因此,对于化简器,您必须始终返回除未定义之外的任何值。

最新更新