I'm trying to display the comments of each photo when clicked the button. Got stuck with setObj function. When I click I can change the boolean but also it pushes another item named "true" to the array.
export default function App() {
const [obj, setObj] = useState([
{ name: "chicken", comments: "nice", photo: img, boolean: false },
{ name: "beef", comments: "ehh", photo: img, boolean: false },
{ name: "turkey", comments: "not bad", photo: img, boolean: false },
{ name: "broccoli", comments: "cool", photo: img, boolean: false },
{
name: "carrot",
comments: "disgusting",
photo: img,
key: 4,
boolean: false
}
]);
const handleClick = (e) => {
const idx = e.target.value;
setObj(prev =>
[...prev, prev[idx].boolean = true]
)
console.log(obj);
};
return (
<div>
{obj.map((map, key) => (
<div>
<img src={map.photo} alt={map.key} />
<h1>{map.name}</h1>
<p>{`${map.boolean}`}</p>
<p>{key}</p>
Haven't done the neccessary changes here coz i got stuck with setState function.
<button value={key} onClick={handleClick}>
show comments
</button>
</div>
))}
</div>
);
}
//onClick={(e) => {
//map.boolean = !e.target.value
//setObj([...obj])
//}}value={map.boolean}
CodePudding user response:
Well, this is actually what you are doing there, you are spreading an array and adding an item after that! what you could do:
const handleClick = (e) => {
const idx = e.target.value;
setObj(prev => {
prev[idx].boolean = true;
return prev;
}
)
console.log(obj);
};
this would work most likely.
also for this kind of huge states I suggest you consider useReducer
from react.
CodePudding user response:
The issue is here
setObj(prev =>
[...prev, prev[idx].boolean = true]
)
You're actually pushing another boolean value modify handleClick function as such
const handleClick = (e) => {
const idx = e.target.value;// getting the required idx
const newObj = JSON.parse(JSON.stringify(obj)); // creating a new obj
obj[idx].boolean = true; // setting the newobj boolean value
setObj(newObj); // useState function to set new state.
};
CodePudding user response:
This is what's called a destructuring assignment
[...prev, prev[idx].boolean = true]
You basically say.. Hey, take this object, spread it's values, then assign this new value and append it. The problem with this is that you're creating a new variable prev[idx].boolean
and assigning a new value to it true
. That's the root of the problem.
Now, what you should do is create this variable outside
const value = { ...prev[idx] }
value.boolean = true
You should create a new object otherwise it's passed by reference.
In Pass by Reference, a function is called by directly passing the reference/address of the variable as the argument. Changing the argument inside the function affects the variable passed from outside the function. In Javascript objects and arrays are passed by reference.
Then assign it
setObj(prev =>
[...prev, value]
)
This means you will override any destructured element with the same value or if it doesn't have any, just assign the new value.