Reputation:
Good afternoon, I get json from the server, I process it, but the call to render occurs 2 times.Google, make an empty object in the constructor.And if the object has no property, then undefined is returned, but I also have arrays, from which the application crashes.I attach the code. How to get the data out of the state? Is it possible to fetch in the render and write?
export default class Forma extends React.Component {
constructor(props) {
super(props);
this.state = { data: [] };
}
componentWillMount() {
fetch("http://localhost:3001")
.then(response => response.json())
.then(result => this.setState({ data: result }))
.catch(e => console.log(e));
}
render() {
const { data } = this.state;
return <h1>{console.log(data.goals[0].gs_id)}</h1>; //падает
}
}
Upvotes: 3
Views: 436
Reputation: 15688
Use an extra state-value that you can toggle when the data has finished fetching. That will help prevent the attempt of using an object property inside an empty array.
export default class Forma extends React.Component {
constructor(props) {
super(props);
this.state = {
loading: true,
data: []
};
}
componentDidMount() {
fetch('http://localhost:3001')
.then(response => response.json())
.then(result => this.setState({ loading: false, data: result }))
.catch(e => {
this.setState({ loading: false })
console.log(e)
});
}
render() {
const { loading, data } = this.state;
if (loading) {
return <span>Loading</span>;
}
if (!data || data.length === 0) {
return <span>No items found</span>;
}
return <h1>{data.goals[0].gs_id}</h1>;
}
}
Upvotes: 4
Reputation: 7299
Use componentDidMount
instead of componentWillMount
, it's deprecated.
And that's a really good addition in Christopher's answer to handle async operation.
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
data: []
};
}
componentDidMount() {
fetch("https://jsonplaceholder.typicode.com/todos")
.then(response => response.json())
.then(result =>
this.setState({
data: result
})
)
.catch(e => console.log(e));
}
render() {
const { data } = this.state;
return <h1> {data[0] ? data[0].title : 'Loading'} </h1>;
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Upvotes: 6