Search code examples
javascriptreactjsarraysobjectreact-hooks

Remove an element from the array inside an object in React using UseState hook


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>
    ))}


Solution

  • 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:

    console.log(tempArray === dives); //will always return true, so no change
    setDives([...tempArray]);