Реагировать useReducer найти и изменить один объект в состоянии - PullRequest
1 голос
/ 04 апреля 2020

У меня есть объект состояния, который содержит массив внутри имен rows. Этот массив содержит список объектов:

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

Теперь в форме я отправляю действие, что полезная нагрузка содержит точно такой же объект, единственными отличиями являются ключи S, M, L, XL, который может измениться.

Затем в моем редукторе я хочу найти в своем исходном состоянии тот же объект, сопоставив его с _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 Ответ

1 голос
/ 04 апреля 2020

Основная проблема, с которой вы столкнулись, заключается в том, что вы должны по умолчанию state.rows быть массивом, чтобы ошибка типа прекратилась. Кроме того, из того, что я вижу, ваша логика c выглядит нормально.

РЕДАКТИРОВАТЬ:

Хорошо, похоже, ваша проблема заключалась в том, что вы не возвращали полное состояние, когда вы были запущены дело "UPDATE_ROW". Если вы используете это, я считаю, что проблема должна быть исправлена.

Я также исправил логи c в корпусе редуктора. Выглядело так, как будто вы добавляете весь объект полезной нагрузки в свойство _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;
  }
};
...