React/Redux reducer 在初始化期间返回 undefined

React/Redux reducer returned undefined during initialization

我正在做我的第一个 React/Redux 项目。一切顺利,然后我尝试创建一个新的减速器。我认为这是一个非常简单的方法,但是当我加载页面时出现错误 "Reducer X returned undefined during initialization." 跟踪表明这是在 combineReducers() 中发生的。我发现了几个类似的问题,但他们没有解决问题。

关于这个问题:

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

关于这个问题:

问题是我拥有的减速器中缺少默认 return 值。

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

reducers/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;
}

reducers/index.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 没有错误。我已经对我的文件路径进行了两次、三次和四次检查。我没有看到任何错别字。谁能看到我在这里遗漏的东西?

I have a console.log() at the beginning and it is not being called at all.

这很奇怪,因为 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)
  }
}

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

Redux 的要求是对操作使用 type 属性,而不是像您在示例中所做的那样 which。由于未调用您的 console.log 检查,问题可能出在您的其他减速器中(未在您的问题中显示。)

这很重要的原因是 combineReducers 正在调用具有特殊 INIT 操作类型的减速器函数:

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

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

你的函数,因为它打开 'action.which' 而不是 'action.type',无法 return 除了未定义的任何东西。

当您的 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 语句

当组装一个 reducer 时,在你的 switch 语句中你将传递一个来自 action creators type 属性 的 action.type。 action creator 中没有 which 属性 它将传递给 reducer。

请记住动作创建者总是将普通的 JavaScript 动作对象传递给缩减器。即使它的函数被 Redux-Thunk 等中间件接收,该中间件最终也会将 action creators 函数修改为 action 对象,以发送到所有 reducer。

此外,您的案例需要是操作类型本身的值。所以假设你的动作创建者是异步的,它从某个端点获取数据,它看起来像这样:

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

除了你的 switch 在操作 type 属性 中传递之外,大小写必须是那个 type 属性 的值,在这个例子中 'ALL_TIME' 并且你想要 return 动作创建者的有效载荷,如果你告诉我 payload 属性 是 returning which,那么上面看起来像这样:

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

否则,您很可能会 returnpayload: 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’;
};

您可以return一个空数组:

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

您可以return一个对象:

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

你甚至可以像这样 return null 的值:

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

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

export default () => {
  return undefined;
}

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

您看到错误提示 returned undefined during initialization。因此,当 Redux 首次启动时,它会 运行 每个减速器一次。

所以这意味着你的 reducer 第一次 运行 它 returned 的值是 undefined,你的 reducer 永远不会 return undefined,无论是在初始化还是在某个时候将来当一个动作被调度时。

所以对于 reducer,你必须总是 return 除了 undefined 之外的任何值。