Reputation: 1538
I have a state object that contains an array inside names rows
. This array contains a list of objects:
{_id: "5e88ad4c5f6f7388d50b9480",
stampa: "Confezione",
S: 0,
M: 0,
L: 0,
XL: 0,
coloured: "",
modello: "",
SKU: ""}
Now, in a form I dispatch an action that the payload contains exactly the same object, the only differences are the keys S
, M
, L
, XL
that can change.
Then, in my reducer, I want to find in my original state the same object by matching with _id
, and then update it with the object that comes with the payload.
This is my attempt, however I am getting the following error:
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
);
How can I tackle this in a better way?
EDIT: This is my reducer:
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;
}
};
And this is my 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>
);
};
Upvotes: 3
Views: 2179
Reputation: 11027
The main issue you are having there is that you should default state.rows to be an array in order for the type error to stop. Other than that, from what I see there, your logic seems fine.
EDIT:
Okay, looks like your issue was that you weren't returning the full state when you were running the "UPDATE_ROW" case. If you use this, I believe the issue should be fixed.
I also fixed the logic in the reducer case as well. It looked like you were adding the entirety of the payload object in the _id property while keeping the rest of the row the same. Rather than update the row with the payload property.
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;
}
};
Upvotes: 4