I want to render a component based on the payload it receives from an api like below
<Route path="/foo/bar" render={() => {
return (get('/some/api').then((res) => {
return <Baz data={res.data} />
}).catch((err) => console.log))
}} />
But I'm getting the error:
Objects are not valid as a React child (found: [object Promise]). If you
meant to render a collection of children, use an array instead.
even when I do wrap Baz
in []
With Suspense, you have the ability to suspend component rendering while async data is being loaded. You can pause any state update until the data is ready, and you can add async loading to any component deep in the tree without plumbing all the props and state through your app and hoisting the logic.
Async-react-router is react router that can easily get initial props using async/await or promise. If you use this library, You can get the initial props like Next. js. And this library works only on client also.
The 'react-router' library is now split into three separate packages. react-router-dom: Designed for web applications. react-router-native: Designed for mobile applications. react-router-core: Can be used anywhere for core applications.
Async component is the classic interface of React Async, and we can use it to make React components more declarative. Here, we can directly use the <Async> component in JSX to apply the render props pattern. Following is a simple example of using <Async> component to fetch data.
unfortunately with the latest version of React - 16. Async rendering is not an option yet.
With React Router v4, the render
props of Route
component expects a valid React Element or array of React Elements to be returned, therefore, it doesn't accept the Promise object return from your function.
However, it's not impossible to achieve what you want with the current version of React and React Router. You just need to tweak your code a little bit. Instead of returning a Promise, your render
should return a React Component, then you can do conditional rendering based on async value inside that component.
It should look like:
<Route path="/foo/bar" render={BazWrapper} />
class BazWrapper extends React.Component {
// Do asynchronous action here
async componentDidMount() {
try {
const apiValue = await get('/some/api');
this.setState({ apiValue })
} catch(err) {
// error handling
}
}
render() {
const { apiValue } = this.state;
return <Baz data={apiValue} />;
}
}
By calling setState
after the asynchronous call finish, you let React Component know that the data is ready and it's should re-render the component.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With