Search code examples
javascriptreactjsecmascript-6spread-syntax

JavaScript | Spread operator update nested value


I am trying to update a nested value of an object using the spread operator. This is my first time using this and I believe I am pretty close to achieving my end goal but I just can't seem to figure out what I actually need to do next.

I have an array which is structured like this:

[
    {
        name: "Category 1",
        posts: [
            {
                id: 1,
                published: false,
                category: "Category 1"
            },
            {
                id: 2,
                published: true,
                category: "Category 1"
            }
        ]
    },
    {
        name: "Category 2",
        posts: [
            {
                id: 3,
                published: true,
                category: "Category 2"
            },
            {
                id: 4,
                published: true,
                category: "Category 2"
            }
        ]
    }
]

On the click of a button I am trying to update the published value, and as I am using React I need to set the state. So it got recommended to me that I update using the spread operator.

onPostClick(post) {
    post.pubished = !post.published;
    this.setState({...this.state.posts[post.category], post})
}

If I log out the result of {...this.state.posts[post.category], post} I can see that the published is getting added to the parent which forms:

{
    name: "Category 1",
    published: false,
    posts: [
        ...
    ]
}

Obviously this isn't the intended result, I want it to update the actual object within the posts object.

I have tried to do something like this.setState({...this.state.posts[post.category].posts, post}) but I get a message that it is undefined.


Solution

  • You can't access your data with this.state.posts[post.category]. posts data in the objects of the array.

    You can make a filter to find your category object in array and change its posts value.

    onPostClick(post) {
        //CLONE YOUR DATA
        var postArray = this.state.posts;
    
        //FIND YOUR CATEGORY OBJECT IN ARRAY
        var categoryIndex = postArray.findIndex(function(obj){
            return obj.name === post.category;
        });
    
        //FIND YOUR POST AND CHANGE PUBLISHED VALUE
        postArray[categoryIndex].posts.forEach(function(item){
           if (item.id === post.id) {
               item.published = !item.published;
           } 
        });
        //SET TO STATE TO RERENDER
        this.setState({ posts: postArray});
    }
    

    This should work if your name of the state is true.