【问题标题】:I get an error when i test my reducer created with redux测试使用 redux 创建的减速器时出现错误
【发布时间】:2021-03-11 21:22:39
【问题描述】:

我收到此错误:

   Reducer "menu" returned undefined during initialization. If the state passed to the reducer is 
   undefined, you must explicitly return
   the initial state. The initial state may not be undefined. If you
   dont want to set a value for this reducer, you can use null instead
   of undefined.

   5 | import { rootReducer } from "./reducers/rootReducer";
   6 | 
>  7 | const reducers = combineReducers({
     |                  ^
   8 |   root: rootReducer,
   9 |   menu: menuReducer,
  10 |   searcher: searchReducer,

  at node_modules/redux/lib/redux.js:378:13
      at Array.forEach (<anonymous>)
  at assertReducerShape (node_modules/redux/lib/redux.js:371:25)
  at combineReducers (node_modules/redux/lib/redux.js:436:5)
  at Object.<anonymous> (src/store/store.ts:7:18)
  at Object.<anonymous> (src/store/actionCreator.ts:1:1)
  at Object.<anonymous> (src/store/initialState.ts:5:1)
  at Object.<anonymous> (src/store/reducers/rootReducer.ts:1:1)
  at Object.<anonymous> (src/tests/rootReducer.test.ts:1:1)

  console.error node_modules/redux/lib/redux.js:325
  No reducer provided for key "root"

  Test Suites: 1 failed, 1 total Tests:       0 total Snapshots:   0
  total Time:        1.175s Ran all test suites related to changed
  files.

在测试这个 reducer (rootReducer.ts) 时:

import { rootInitialState, Reducer, action } from "../initialState";

class RootReducer implements Reducer {
  private initialState: object;

  public constructor(initialState: object) {
    this.initialState = initialState;
  }

  private addNewText = (currentTexts: object, newText: object): object => {
    let newTexts: object = { ...currentTexts };
    newTexts[newText["name"]] = newText["text"];
    return newTexts;
  };

  private switchBodyScroll = (
    payload: "LOCK" | "UNLOCK"
  ): "LOCKED" | "UNLOCKED" => {
    if (payload === "LOCK") {
      document.getElementsByTagName("body")[0].classList.add("scroll-lock");
      return "LOCKED";
    } else {
      document.getElementsByTagName("body")[0].classList.remove("scroll-lock");
      return "UNLOCKED";
    }
  };

  public reduce = (
    state: object = this.initialState,
    action: action
  ): object => {
    if (action.type === "SWITCH_BODY_SCROLL") {
      return {
        ...state,
        bodyScrollState: this.switchBodyScroll(action.payload),
      };
    } else if (action.type === "SWITCH_MINIMAP_MODE") {
      return {
        ...state,
        minimap: {
          ...state["minimap"],
          mode: action.payload.minimapClassList,
          buttonClassList: action.payload.buttonClassList,
        },
      };
    } else if (action.type === "SET_THEMES") {
      return { ...state, themes: [action.payload.items] };
    } else if (action.type === "SET_CURRENT_PAGE") {
      return {
        ...state,
        currentPageId: action.payload.id,
        nextPage: action.payload.next,
        currentPage: [...action.payload.components],
      };
    } else if (action.type === "ADD_NEW_TEXT") {
      return {
        ...state,
        texts: { ...this.addNewText(state["text"], action.payload) },
      };
    } else if (action.type === "SET_PAGE_SEARCHER_VALUE") {
      return { ...state, pageSearcherValue: action.payload };
    } else {
      return state;
    }
  };
}

export const rootReducer = new RootReducer(rootInitialState).reduce;

例如,menuReducer.ts。它包含默认状态,但无论如何返回未定义:

import { menuInitialState, Reducer, action } from "../initialState";

class MenuReducer implements Reducer {
  private initialState: object;

  public constructor(initialState: object) {
    this.initialState = initialState;
  }

  public reduce = (
    state: object = this.initialState,
    action: action
  ): object => {
    if (action.type === "SWITCH_MENU_MODE") {
      return { ...state, compactMenuCurtain: action.payload };
    } else {
      return state;
    }
  };
}

export const menuReducer = new MenuReducer(menuInitialState).reduce;

使用此测试 (rootReducer.test.ts):

import { rootReducer } from "../store/reducers/rootReducer";

it("rootReducer should return LOCKED with payload LOCK", () => {
  expect(
    rootReducer(undefined, { type: "SWITCH_BODY_SCROLL", payload: "LOCK" })
  ).toBe("LOCKED");
});

store.ts 文件如下所示:

import { combineReducers, createStore } from "redux";

import { menuReducer } from "./reducers/menuReducer";
import { searchReducer } from "./reducers/searchReducer";
import { rootReducer } from "./reducers/rootReducer";

const reducers = combineReducers({
  root: rootReducer,
  menu: menuReducer,
  searcher: searchReducer,
});

export const store = createStore(reducers);

我尝试对其他减速器进行相同的测试。我得到了类似的错误。 当然,我已经检查了菜单减速器并尝试测试其他类似的减速器。我得到类似的错误。此外,如果没有给出,每个减速器都将初始状态设置为默认值。我的应用程序在浏览器中运行没有任何错误,我只有通过测试才能得到。任何导入的东西都是 .ts 文件。也许,我只是错过了一些东西 - 现在我正在学习开玩笑。

即使我只是将减速器写入控制台或获取此类型(menuReducer.test.ts),我也会遇到相同的错误:

import { menuReducer } from "../store/reducers/menuReducer";

it("rootReducer should return LOCKED with payload LOCK", () => {
  console.log(menuReducer);
  console.log(typeof menuReducer); // That's a method of class
});

【问题讨论】:

  • 当然,我已经检查了菜单缩减程序,如果没有给出默认设置,那么我已经将初始状态设置为默认值 - 那么请让其他人也这样做。 stackoverflow.com/help/mcve 是代码相关问题所必需的。

标签: reactjs testing redux jestjs


【解决方案1】:

好的,我已经解决了这个问题。无论如何,这看起来很奇怪。如果有人有同样的东西,他需要一个解决方案。解决方案:由于某种原因,我不能只导入我的减速器并将其用作默认方法或类似方法。正式地说:“嘿,伙计,我没有东西可以给减速器,只是接受一个无法帮助你的错误。”。我初始化了我的状态(使用导入的商店并调用它的 getState()),这开始工作了。代码是(rootReducer.test.ts):

import { store } from "../store/store";
import { rootReducer } from "../store/reducers/rootReducer";
import { action } from "../store/initialState";

describe("rootReducer test failed", (): void => {
  store.getState(); // Initialize state (looks like this boy allow to use reducers only when you call it)

  it("should return LOCKED with payload LOCK and option SWITCH_BODY_SCROLL", (): void => {
    const switchBodyScrollAction: action = {
      type: "SWITCH_BODY_SCROLL",
      payload: "LOCK",
    };

    const newState: object = rootReducer(undefined, switchBodyScrollAction);

    expect(newState["bodyScrollState"]).toBe("LOCKED");
  });
});

测试通过了,但我不知道为什么我不能只使用 reducer 作为另一种方法; 顺便说一句,其他减速器的行为相同。

【讨论】:

    猜你喜欢
    • 2020-04-20
    • 2016-06-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-19
    • 1970-01-01
    • 2017-05-09
    • 1970-01-01
    相关资源
    最近更新 更多