jpc
jpc

Reputation: 139

How to update React component when async prop promise resolves?

Lets say I have a component that renders a PivotGrid component. This PivotGrid takes some data, an array of objects.

function My_component(props) {
    return <PivotGrid dataSource={props.data} />
}

However, the data prop that I want to pass in is the result of an async function.

const get_data = async () => {
    return await o(url, options).get('foo').query({})
}

ReactDOM.render(<My_component data={get_data()}/>, document.getElementById('root'));

What happens is that the component renders before the promise from get_data() is resolved, and the PivotGrid has no data.

What I would like to happen is for the component to re-render when the promise resolves and actually returns data. I've tried variations of React's useState() to treat props.data as a state variable, so that when the promise returns the state would change the the component would update. But this has not worked yet.

const [gridData, setGridData] = useState(props.data);
props.data.then((r) => {
    setGridData(props.data)
})

Attempts like the above all fail. What is the best way to achieve this functionality, where the component re-renders when prop.data resolves and actually holds the data I want?

Upvotes: 0

Views: 3115

Answers (2)

Ilyas Assainov
Ilyas Assainov

Reputation: 2069

Using hooks and the container component for My_component should work.

my-component-container.js:

import React, {useState, useEffect} from 'react'
import My_component from './my-component'

export default () => {
   const [data, setData] = useState(null)
   useEffect(async () => {
     const fetchData = async () => {
         const result = await o(url, options).get('foo').query({})

         setData(result);
     };

    fetchData();
   }, [])

   return <My_component dataSource={data} />
}

In your entry point:

import My_component_container from './my-component-container'

ReactDOM.render(<My_component_container />, document.getElementById('root'))

Upvotes: 1

Nana Koduah
Nana Koduah

Reputation: 66

Why not change to a stateful component like below

class My_component extends React.Component {
   state = {};

   componentDidMount(){
     this.get_data()
   }

   get_data = async () => {
     const data = await o(url, options).get('foo').query({});
     this.setState({ data });
   }

   render() {
      const { data } = this.state;
      return <PivotGrid dataSource={data} />
   }

}

Upvotes: 0

Related Questions