简体   繁体   中英

React.js - how do I call a setState function after another one has finished

I must be missing something obvious here. I have a to-do list app which uses a function for creating new lists. Once createList is called I want to then highlight the list by setting its selected prop to true So below are the two methods for doing this. I'm trying to call one after the other. Both of them modify state using the appropriate callback that uses prevState , yet for whatever reason createList does not set the new list in state before toggleSelected gets called, and so listName is undefined in toggleSelected . Is there anyway to ensure the new list object is set in state before calling toggleSelected ? I should probably be using Redux but I didn't want to get into it for my first React app.

createList = (listName) => {
  const lists = {...this.state.lists};
  lists[listName] = {
    listName: listName,
    selected: false,
    todos: {}
  };

  this.setState(prevState => {
    return {lists: prevState.lists};
  });
};

toggleSelected = (listName) => {
    let selected = this.state.lists[listName].selected;
    selected = !selected;
    this.setState(prevState => {
      return {
        bookLists: update(prevState.lists, {[listName]: {selected: {$set: selected}}})
      };
    });
};

Both methods are called in another component like so after an onSubmit handler with the new list name being passed in:

this.props.createList(newListName);
this.props.toggleSelected(newListName);

PS - If you're wondering what's up with update() , it's from an immutability-helper plugin that allows for easily setting nested values in a state object(in this case, state.lists[listName].selected )--another reason I probably should have gone with Redux.

PPS - I realize I can just set the new list's selected prop to true from the start in creatList but there's more to the app and I need to set it after creation.

Don't do what you're doing in toggleSelected right now, instead toggle the selected flag in your list (without extracting it) and then let your component know you updated the lists data by rebinding the resulting object:

class YourComponent {
  ...
  toggleSelected(listName) {
    let lists = this.state.lists;
    let list = lists[listName];
    list.selected = !list.selected;
    this.setState({ lists });
  }
  ..
}

Then make sure that in your render function, where you create the UI for each list, you check whether selected is true or false so you can set the appropriate classNames string.

(Also note that in your code, you used selected = !selected . That isn't going to do much, because you extracted a boolean value, flipped it, and then didn't save it back to where it can be consulted by other code)

The problem is not in the second setState function. It is at the first line of the toggleSelected() method.

When the toggleSelected() method is executed, the first setState haven't been executed.

The flow of the your code is:

  1. createList();
  2. toggleSelected();
  3. setState() in createList();
  4. setState() in toggleSelected();

Solution 1: Use await and async keywords

Solution 2: Use redux

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM