kevin
kevin

Reputation: 309

React Concurrent Modify Same State

I get errors while modifying a state concurrently. I have a function called getAvailableSpace(i, newValue) which fetch data from the back end and set to the state. This function can be called concurrently. The errors happen when it is called before the last call finished.

getAvailableSpace(i, newValue) {
    this.setState(() => {
        let schema_filters = _.cloneDeep(this.state.schema_filters);
        schema_filters[i].loadingSpaces = true;
        return {schema_filters: schema_filters}
    }, () => {
        this.invokeAPI("sitecomparsion", "getallspaces" + this.props.router.location.search + "&selectedTdid=" + newValue.value, requestHeaders.getHeader, (data) => {
            let schema_filters = _.cloneDeep(this.state.schema_filters);
            if(data) {
                //schema_filters[i].availableSpaces = {...data.spaces, ...data.areas}
                let spaces= (Object.keys(data.spaces).map((key) =>{
                    return {label: data.spaces[key], value: ('space_' + Number(key))}
                }))

                schema_filters[i].availableSpaces = [];
                schema_filters[i].availableSpaces.push({label: 'Spaces:', type: 'optgroup'})
                schema_filters[i].availableSpaces = schema_filters[i].availableSpaces.concat(areas)
            }
            this.setState((prevState) => {
                prevState.schema_filters = schema_filters;
                return prevState;
            });
        });
    });
}

The problem I believe is caused by the race condition since two calls are trying to modify the same state.

Also, I think if the _.cloneDeep(this.state.schema_filters) happens before the last call is finished, the update from the last call is lost. Can I get some help?

Upvotes: 1

Views: 377

Answers (1)

hong developer
hong developer

Reputation: 13906

If you have a lot of status to update at once, group them all in the same set. State:

this.setState(() => {
   this.setState(() => {
        let schema_filters = _.cloneDeep(this.state.schema_filters);
        schema_filters[i].loadingSpaces = true;
        return {schema_filters: schema_filters}
    this.setState({schema_filters: schema_filters }, () => { 
    // Do something here. 
  });
});

Upvotes: 1

Related Questions