How to render data received from a REST service in React Universal? (Next.js)
I want to receive data via a call to a REST service in a React Universal app (with Next.js) using fetch()
and then render the result in JSX like this:
class VideoPage extends Component {
componentWillMount() {
console.log('componentWillMount');
fetch(path, {
method: 'get',
})
.then(response =>
response.json().then(data => {
this.setState({
video: data,
});
console.log('received');
})
);
}
render() {
console.log('render');
console.log(this.state);
if (this.state && this.state.video) {
return (
<div>
{this.state.video.title}
</div>
);
}
}
}
export default VideoPage;
Unfortunately, the output is as follows:
componentWillMount
render
null
received
Which makes sense, because the call to retrieve is done asynchronously and render()
ends before the call to the REST service completes.
In a client application, this is not an issue because a state change will trigger render()
which then updates the view, but in a universal application, especially with JavaScript disabled on the client, this is not possible.
How can I solve this?
Is there a way to call the server synchronously or delay render()
?
source to share
To make it work, I had to do 3 things:
- Replace
componentWillMount
with getInitialProps () method - Combine
fetch
withawait
and return data - Use
this.props
insteadthis.state
Now the code looks like this:
static async getInitialProps({ req }) {
const path = 'http://path/to/my/service';
const res = await fetch(path);
const json = await res.json();
return { video: json };
}
Then in render()
I can access the data via this.props.video
for example:
render() {
return (
<div>{this.props.video.title}</div>
);
}
source to share
You can add static async getInitialProps () {}
to load data in props before the page component gets rendered.
More info here: https://github.com/zeit/next.js/blob/master/readme.md#fetching-data-and-component-lifecycle
source to share