React useReducer查找并更改状态下的单个对象

时间:2020-04-04 16:34:09

标签: javascript reactjs ecmascript-6 react-hooks

我有一个状态对象,其中包含一个名称为rows的数组。此数组包含对象列表:

{_id: "5e88ad4c5f6f7388d50b9480",
stampa: "Confezione",
S: 0,
M: 0,
L: 0,
XL: 0,
coloured: "",
modello: "",
SKU: ""}

现在,以一种形式,我调度一个有效载荷包含完全相同的对象的动作,唯一的区别是键SMLXL可以改变。

然后,在我的化简器中,我想通过与_id匹配来找到原始状态的相同对象,然后使用有效负载随附的对象对其进行更新。 这是我的尝试,但是出现以下错误:

TypeError: state.rows.map is not a function

case "UPDATE_ROW":
      return state.rows.map((row) =>
        row._id === action.payload._id
          ? {
              ...row,
              _id: action.payload,
            }
          : row
      );

我该如何更好地解决这个问题?

编辑: 这是我的减速器:

export default (state, action) => {
  switch (action.type) {
    case "UPDATE_STATE":
      return {
        ...state,
        rows: action.payload,
      };
    case "SET_ERROR":
      return {
        ...state,
        error: action.payload,
      };
    case "UPDATE_ROW":
      console.log("updating", action.payload);
      return state.rows.map((row) =>
        row._id === action.payload._id
          ? {
              ...row,
              _id: action.payload,
            }
          : row
      );

    default:
      return state;
  }
};

这是我的状态:

import React, { createContext, useReducer } from "react";
import AppReducer from "./AppReducer";

// Initial State
const initialState = {
  rows: [],
};

export const GlobalContext = createContext(initialState);

// Provider component
export const GlobalProvider = ({ children }) => {
  const [state, dispatch] = useReducer(AppReducer, initialState);
  console.log(state);

  return (
    <GlobalContext.Provider value={[state, dispatch]}>
      {children}
    </GlobalContext.Provider>
  );
};

1 个答案:

答案 0 :(得分:1)

您遇到的主要问题是,应默认将state.rows设置为数组,以停止类型错误。 除此之外,从我所看到的来看,您的逻辑似乎还不错。

编辑:

好吧,看来您的问题是在运行“ UPDATE_ROW”案例时您没有返回完整状态。如果使用此选项,我相信该问题应已解决。

我也固定了减速器情况下的逻辑。看起来您在_id属性中添加了整个负载对象,而其余行保持不变。而不是使用有效负载属性更新行。

export default (state, action) => {
  switch (action.type) {
    case "UPDATE_STATE":
      return {
        ...state,
        rows: action.payload,
      };
    case "SET_ERROR":
      return {
        ...state,
        error: action.payload,
      };
    case "UPDATE_ROW":
      console.log("updating", action.payload);
      return {...state, rows:state.rows.map((row) =>
        row._id === action.payload._id
          ? {
              ...action.payload
            }
          : row
      )};

    default:
      return state;
  }
};