0

I'm trying to update an object in an array which is in my state.

I have an array of objects 'this.state.webs' which is presented in multiple div`s on a page. Each one has an onclick method which send the object to a function, then I do an API call and returns a set of 'sub webs' which I want to add to the object in the property 'subs'.

My state:

this.state = {
  webs: this.props.webs
}

My template:

<Nav
   groups={[
     {
       links: this.state.webs
     }
   ]}
   expandedStateText={'expanded'}
   collapsedStateText={'collapsed'}
   selectedKey={'key3'}
   onLinkClick={this._openWeb.bind(this)}
 />

Onclick function:

  private async _openWeb(r, n): Promise<void> {
    const service = new MyService();
    var subs = await service.getSubs(n);

    n.subs = subs;

    ### How do I update 'n' with the subs? setState({ ? })
  }

So, when a user clicks a web, I am fetching some sub webs and then I want to update the parent object n with the children (subs).

3 Answers 3

1

You can update your webs array with everything before n, a clone of n with the updated subs, and everything after n:

private async _openWeb(r, n): Promise<void> {
  const service = new MyService();
  const subs = await service.getSubs(n);

  const { webs } = this.state;
  const nIndex = webs.indexOf(n);

  this.setState({
    webs: [
      ...webs.slice(0, nIndex),
      { ...n, subs },
      ...webs.slice(nIndex + 1)
    ]
  })
}
Sign up to request clarification or add additional context in comments.

6 Comments

This works as expected :) I'm still a bit baffeled by the complexity of something so fundamental.
What if I need to update an object which is further down in the structure? Lets say one of the objects in the array subs had another array with subs? I'm struggeling to see how this is solved. It's completely dynamic, so it could be 5 levels of nested subs.
@ffffff01 Nested arrays gets pretty hairy with immutable data. If you e.g. would want to change a nested links array, you could find the index of your web and also the index of your link and do the same process twice.
My issue is that I dont know the web when the sub is clicked. I guess I need to add some additional data like a parent property or something.. I miss my angularjs projects right now :)
@ffffff01 I can't say for certain, but if you know what sub is clicked, you most likely know what web is clicked as well, since I guess you are looping over all webs and their subs. E.g. _openSub(web, sub)
|
1

Based on the answer from Tholle and Filip W, I came up with my own approach.

Gladly to recieve some comments if this approach isn't recommended, but I find it easier to understand than the suggestion from Tholle.

const webs = [...this.state.webs];
const index = webs.indexOf(n);
webs[index].links = links;
webs[index].isExpanded = true;
this.setState({webs})

1 Comment

This is a nice solution. Just make sure that you don't mutate your webs[index] object. webs[index] = { ...n, links, isExpanded: true };
-1

From my experiences with presenting array of data it was useful to also send an index of the targeted object (or div where click happened). So something like this could be useful:

   const webs = this.state.webs
   webs[index].subs = subs
   this.setState({webs})

2 Comments

You mutate webs
webs is reference to the object this.state.webs

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.