How to use async/await promises with React props/state?

Viewed 9446

I'm trying to dynamically load properties into a React component. The properties are set in this.props.customObjects using fetch with async/await higher up in the component structure.

My CustomObject component (below) receives the properties in the form of a promise, but I fail in actually showing the fetched data in the component. I guess my component renders before the promise has resolved.

What's the best way to solve this? Can values from async/await be used in props, or do I have to use state?

My component:

export default class CustomObject extends React.Component {

    getCustomObject = (elementType) => {
        const customObject = this.props.customObjects[elementType];
        console.log('customObject', customObject);
        return customObject;
    }

    componentDidMount() {
        const customObject = this.getCustomObject(this.props.element.elementType)
        this.setState({ customObject });
    }

    render () {
        return <div className={this.props.className} style={this.props.style}>
            {this.state.customObject.name} // Gives TypeError: Cannot read property 'customObject' of null
        </div>
    }

}

The console log looks like:

console.log

2 Answers

If it's a promise you can say something like:

customObject.then((result) => {
    this.setState({customObject: result})
})

As you're waiting for something, you need to use setState to get re-render. You should put in a fallback, in case the promise is still pending in your render() when it is first called.

There is a couple of ways to handle your situation. One of them is if this.getCustomObject(...) is returning a Promise, you can wait for it to resolve and then set the state.

For Example

this.getCustomObject(this.props.element.elementType).then((customObject) => {
  this.setState({ customObject });
});

For more information about Promise please check here.

This would not completely solve your problem if you don't give a default value for this.state.customObject since its gonna be undefined till the Promise resolved. You can use something like {this.state.customObject ? this.state.customObject.name : 'Loading..'}

Related