I want to receive data via a REST service call in my React Universal (with Next.js) app using fetch()
and then render the result into 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 this:
componentWillMount
render
null
received
Which does make sense because the call to fetch is asynchronously and render()
finishes before the call to the REST service has finished.
In a client-side app this would be no problem because a change of state would call render()
which then updates the view, but in a universal app, especially with JavaScript turned off on the client, this is not possible.
How can I solve this?
Is there a way to call the server synchronously or delay render()
?
In order to get it working, I had to do 3 things:
componentWillMount
with getInitialProps() methodfetch
with await
and return the datathis.props
instead of this.state
Code looks like this now:
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>
);
}