I've a very simple React Web App
where I want to add new object
of review
to an array
of an object
:-
I'm using useReducer
to handle default state
of my data as show below:-
reducer
function:-
const reducer = (state, action) => {
switch (action.type) {
case "ADD_REVIEW_ITEM":
state.forEach(
(data) =>
data.id === action.payload.selectedDataId &&
data.listOfReview.push(action.payload.newReview)
);
return [...state];
default:
return state;
}
};
default data
for myreducer
:-
const data = [
{
id: 1607089645363,
name: "john",
noOfReview: 1,
listOfReview: [
{
reviewId: 1607089645361,
name: "john doe",
occupation: "hero",
rating: 5,
review: "lorem ipsum"
}
]
},
{
id: 1507089645363,
name: "smith",
noOfReview: 1,
listOfReview: [
{
reviewId: 1507089645361,
name: "smith doe",
occupation: "villain",
rating: 5,
review: "lorem ipsum"
}
]
}
];
App.js
, demo of what's happening:-
import React, { useState, useEffect, useReducer } from "react";
import "./styles.css";
export default function App() {
const [state, dispatch] = useReducer(reducer, data);
// hnadle adding of new review
const handleAddNewReview = (id) => {
dispatch({
type: "ADD_REVIEW_ITEM",
payload: {
selectedDataId: id,
newReview: {
reviewId: new Date().getTime().toString(),
name: "doe doe",
occupation: "doctor",
rating: 5,
review: "lorem ipsum"
}
}
});
};
return (
<>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
{state?.length > 0 &&
state.map((data) => (
<div key={data.id}>
<h1>{data.name}</h1>
{data.listOfReview?.length > 0 &&
data.listOfReview.map((review) => (
<div key={review.reviewId}>
<h3>{review.name}</h3>
<p>{review.occupation}</p>
</div>
))}
<button onClick={() => handleAddNewReview(data.id)}>
Add new review
</button>
</div>
))}
</>
);
}
The problem is, once I clicked the button
for the first time, the state
gets updated right. But if I click it for the second time, it somehow added TWO more of the same review
. How should I change my code
in reducer
to fixed this issue?
This is a working sandbox of said case.