1

What is the best practice in React to push a new object to an array within an object that doesn't have a key and then have the state update? I'm currently able to update it, but it's mutating the state which I know is not a best practice. I'd like to be able to use this.setState so my component re-renders. Thanks!

currentState = {
    lorem: [
        {
            id: 123,
            title: 'quis nostrud'
            ipsum: [
                {
                    dolor: 0,
                    amet: 0
                }
            ]
        },
        {
            id: 456,
            title: 'occaecat cupidatat'
            ipsum: [
                {
                    dolor: 0,
                    amet: 0
                }
            ]
        }
    ]
}

desiredState = {
    lorem: [
        {
            id: 123,
            title: 'quis nostrud'
            ipsum: [
                {
                    dolor: 0,
                    amet: 0
                },
                {
                    dolor: 100,
                    amet: 100
                }
            ]
        },
        {
            id: 456,
            title: 'occaecat cupidatat'
            ipsum: [
                {
                    dolor: 0,
                    amet: 0
                }
            ]
        }
    ]
}
2
  • I think you can solve your problem by using this.setState differently. this.setState(prevState => { // drive your newState from prevState after cloning it return newState; }) Commented May 18, 2020 at 23:58
  • I looked into that, but it seemed like I still needed to know which object's array needs to be updated. Do you have an example that you think would work? Commented May 19, 2020 at 0:03

2 Answers 2

2

Yes you should not mutate the original state directly. You need to find the id of which object you need to update in the array then update the state.

Like this

const updatedLorem = currentState.lorem.map(x => {
    if(x.id === '123') // <----- you will need to know which id to update
        return [...x.ipsum, {dolor: 0, amet: 0}]
    else
        return x
})

this.setState(prev => ({
    ...prev,
    lorem: updatedLorem
}))
Sign up to request clarification or add additional context in comments.

3 Comments

This is great, thank you for the help. I may be over looking something, but when I set the state at the end wouldn't it need to be something along the lines of lorem[desiredObject]['ipsum']: updatedLorem?
this replaces the first lorem array item with the new ipsum array rather than spreading it into the complete object
@JonB That is what I'm experiencing.
1

I have updated the code from @gdh above which was overwriting the lorem object with the new ipsum array.

Here is a working example that instead appends the new object to the correct ipsum array within the lorem object: https://codesandbox.io/s/cool-star-k8kpo?fontsize=14&hidenavigation=1&theme=dark

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.