简体   繁体   中英

Can't update a component's state inside a callback function

constructor(props) {
    this.state = {contents: []};
}

componentDidMount() {
    var self = this;
    console.log('> Manage mounted');
    ServerService.getServers(
        Parse, 
        self.props.parentState.state.activeAccount,
        (error, results) => {
            if (error) {
                throw new Error(error); 
            }

            this.setState((prevState, props) => ({
              contents: results 
            }));
        }
    );
}

Hi there, I have this code above. I have a component named Manage and Servers. Now, from the time the Manage component is mounted, I wanted to populate it's this.state.contents by means of ServerService.getServers() . The utility returns a results , which is an array from a callback function. Though, the state is not getting in. Is this the correct way of updating a component's state from the within a callback function?

Furthermore, I am passing the said state to a child component named MainContent eg <MainContent contents={this.state.contents} /> , and watching it as a props, when the component is mounted

componentDidMount() {
    console.log('> MainContent is mounted');
    console.log(this.props.contents);
}

The thing is, this.props.contents from MainContent component remains a blank array. The reason why I am doing this is because I have further usage of the value in contents , as another sets of props for MainContent child components.

The approach that you are using to update the state is useful in a scenario when you are trying to update a state sort of like

    this.setState((prevState, props) => ({
          contents: [...prevState.content, props.content]
        }));

ie making use of the previous state as well as props because this.props and this.state may be updated asynchronously, you should not rely on their values for calculating the next state.

However you are using setState inside a function and hence this keyword here won't refer to the correct content, you should make use of self also since you are updating the state with a value that is not dependent on state or props and hence you can use the direct approach of updating a state like

self.setState({contents: results});

Code:

componentDidMount() {
    var self = this;
    console.log('> Manage mounted');
    ServerService.getServers(
        Parse, 
        self.props.parentState.state.activeAccount,
        (error, results) => {
            if (error) {
                throw new Error(error); 
            }

            self.setState({
              contents: results 
            });
        }
    );
}

As far as getting a blank array in componentDidMount of MainContent is concerned, you will get a bland array because componentDidMount is rendered only on the initial render and since at initial render your this.state.contents is a blank array, you get a empty value.

change that to componentWillReceiveProps

componentWillReceiveProps(nextProps) {
    console.log("Main content");
    console.log(nextProps.contents);

}

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