I’m trying to remove an element from the array inside an arrays of objects in React using UseState hook, but struggling to get the result, because the interface does not re-render and the object does not removing from it.
As I know, to get any updates of objects reflected in react UI, I should replace a whole object instead of updating it. I was trying to create a copy of an array and assign it through setDives method inside the function, but nothing.
Here is my code:
Declaring const using useState. I need to delete only specific guides by name ("Lee" or "John" in this example):
const [dives, setDives] = useState([
{ boat: 'Marcelo', divesite: '', guides: ['Lee', 'Jhon'] },
]);
Delete function:
function deleteGuide(i, guide) {
var tempArray = dives;
tempArray[dives.indexOf(i)].guides = dives[dives.indexOf(i)].guides.filter(
(e) => e !== guide,
);
setDives(tempArray);
}
Buttons in interface:
{dives.map((i) => (
<div>
{dives[dives.indexOf(i)].guides.map((guide) => (
<ButtonGroup>
<Button>{guide}</Button>
<Button onClick={() => deleteGuide(i, guide)}></Button>
</ButtonGroup>
))}
</div>
))}
3
Answers
You correctly said, that you have to create a new copy of the Array, but you are actually not doing it. That’s why it is not working.
Change this line:
setDives(tempArray);
to this:setDives([...tempArray]);
Explanation: When just setting tempArray, you are updating only the reference, which does not change, because
tempArray = dives
. Since there are no changes, there is no re-render and you do not see any results. By using the spread-operator...
, a completely new Array is constructed and therefor the state changes (which triggers a re-render).Further reading: https://react.dev/learn/updating-arrays-in-state
To make this even more understandable, you can add a console.log before your setDives(tempArray)-statement and take a look at the output:
There’s a couple of things I would recommend.
Add ids to your dataset, both for the dive and for the guides (this will mean changing the guides from a name string to an object with an
id
andname
. It helps mitigate some of the warnings that React will give you when you’remap
ping over arrays and trying to add keys.Use those ids as data attributes on the button element. You can pick them up in the button handler and use them to help your filter your dataset.
You should use the function version of the
setState
when callingsetDives
. You can usestructuredClone
to create a deep copy of the current state.Note: You should also use the
key
prop when callingmap
.