I'm new to reactjs, I want to fetch data in server, so that it will send page with data to client.
It is OK when the function getDefaultProps return dummy data like this {data: {books: [{..}, {..}]}}.
However not work with code below. The code execute in this sequence with error message "Cannot read property 'books' of undefined"
However, I expect the code should run in this sequence
Any Idea?
statics: { fetchData: function(callback) { var me = this; superagent.get('http://localhost:3100/api/books') .accept('json') .end(function(err, res){ if (err) throw err; var data = {data: {books: res.body} } console.log('fetch'); callback(data); }); } getDefaultProps: function() { console.log('getDefaultProps'); var me = this; me.data = ''; this.fetchData(function(data){ console.log('callback'); console.log(data); me.data = data; }); console.log('return'); return me.data; }, render: function() { console.log('render book-list'); return ( <div> <ul> { this.props.data.books.map(function(book) { return <li key={book.name}>{book.name}</li> }) } </ul> </div> ); }
React does not wait to render.There is no way to make it wait. All is not lost, though. There's an easy fix. Components that render async data need to be prepared to render an empty state, at least once.
Using the JavaScript Fetch API. The Fetch API through the fetch() method allows us to make an HTTP request to the backend. With this method, we can perform different types of operations using HTTP methods like the GET method to request data from an endpoint, POST to send data to an endpoint, and more.
componentWillMount() method is the least used lifecycle method and called before any HTML element is rendered. If you want to see then check out the example mentioned above, we just need to add one more method.
What you're looking for is componentWillMount
.
From the documentation:
Invoked once, both on the client and server, immediately before the initial rendering occurs. If you call
setState
within this method,render()
will see the updated state and will be executed only once despite the state change.
So you would do something like this:
componentWillMount : function () { var data = this.getData(); this.setState({data : data}); },
This way, render()
will only be called once, and you'll have the data you're looking for in the initial render.
A very simple example of this
import React, { Component } from 'react'; import { View, Text } from 'react-native'; export default class App extends React.Component { constructor(props) { super(props); this.state = { data : null }; } componentWillMount() { this.renderMyData(); } renderMyData(){ fetch('https://your url') .then((response) => response.json()) .then((responseJson) => { this.setState({ data : responseJson }) }) .catch((error) => { console.error(error); }); } render(){ return( <View> {this.state.data ? <MyComponent data={this.state.data} /> : <MyLoadingComponnents /> } </View> ); } }
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