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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在初始化期间,React / Redux reducer返回undefined相关的知识,希望对你有一定的参考价值。

我正在研究我的第一个React / Redux项目。一切都很顺利,然后我尝试创造一个新的减速机。我认为这是一个非常简单的,但是当我加载页面时,我收到一个错误“Reducer X在初始化期间返回undefined”。跟踪说这发生在combineReducers()中。我发现了几个类似的问题,但他们没有解决问题。

在这个问题上:Why do I get “Reducer [...] returned undefined during initialization” despite providing initialState to createStore()?

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

在这个问题上:Why does my Redux reducer think my state is undefined?

问题是reducer中缺少默认返回值,我有。

我的减速机代码如下。我在开头有一个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;
}

减速器/ 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没有错误。我有双倍,三倍和四倍检查我的文件路径。我没有看到任何拼写错误。谁能看到我在这里失踪的东西?

答案

Redux的要求是在动作上使用type属性,而不是which,就像你在你的例子中所做的那样。由于未调用console.log检查,问题可能在您的其他reducer中(未在您的问题中显示)。

这很重要的原因是combineReducers使用特殊的INIT动作类型调用你的reducer函数:

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

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

你的函数,因为它打开'action.which'而不是'action.type',无法返回除undefined之外的任何内容。

另一答案

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

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

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

const rootReducer = (state = {}, action) => {
  console.log('Test if rootReducer is ever called')

  return {
    campers: Campers(state.campers, action),
    activeSorter: ActiveSorter(state.activeSorter, action)
  }
}

如果它没有被调用,则问题在某个地方更高,而不是在reducer本身。

另一答案

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

还有一个有趣的场景,我正在创建一个基本的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返回undefined,combineReducers函数没有收到预期的对象而是未定义。

确保你有正确的return声明

另一答案

在组合reducer时,在switch语句中,您将从动作创建者action.type属性传入type。动作创建者中没有which属性,它将传递给reducer。

请记住,动作创建者总是将简单的JavaScript动作对象传递给reducers。即使它是由Redux-Thunk等中间件接收的功能,该中间件最终也会将动作创建器功能修改为一个动作对象,以便发送给所有减速器。

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

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

除了在type属性中传递你的开关之外,case必须是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;
}

这在减速机领域是不可接受的。

你看到错误说在初始化期间返回undefined。因此,当Redux首次启动时,它将运行每个减速器一次。

这意味着第一次运行reducer时它返回undefined的值,你的reducer永远不会返回undefined,无论是在初始化时还是在将来调度动作的某个时刻。

因此,对于reducers,您必须始终返回除undefined之外的任何值。

以上是关于在初始化期间,React / Redux reducer返回undefined的主要内容,如果未能解决你的问题,请参考以下文章

react-redux1

React / Redux - 无法读取未定义的属性“XXX”

更新深度嵌套的 react redux 状态数组元素

使用react-router+hooks搭建基础框架

使用 React 和 react-redux-firebase 在登录期间确定范围

无法通过 React 和 Redux 将相同的表单组件用于添加或编辑模式