9

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.

3
  • onPostClick(post) - what is post format, does it contain full data together with id / category etc. ? Commented Nov 24, 2018 at 10:47
  • The format is { id: 1, category: 'Category 1', published: true } Commented Nov 24, 2018 at 10:52
  • So yes @Goran.it it contains all of the data Commented Nov 24, 2018 at 10:52

2 Answers 2

1

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the answer! Before I try this, I just wanted to ask. How come you opted for a for () loop rather than .forEach ? Is there a reason for this or is it personal preference?
@connormiotk96 that came to my mind first. Updated with forEach.
@connormiotk96 what's wrong with for loop? i think you get more flexibility with the length in a for loop.
0

just adding, we know there are many ways to succeed, maybe you also want to try this way too..

onPostClick = post => {
    let published = this.state.data.map((item, i) => {
      item.posts.map((item_post, i) => {
        if (item_post.category === post.category) {
          item_post.published = !post.published;
        }
      });
    });
    this.setState({ ...this.state.data, published });
 };

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.