Reputation:
Good evening. Half a day to write down the result of the query in the state React. All code
import React, { Component } from "react";
import ReactDOM from "react-dom";
import axios from "axios";
export default class AllCalcs extends Component {
constructor (props) {
super(props);
this.state = {
calcs: []
};
this.listItems = '';
this.fetchData();
this.getCalcs();
}
fetchData() {
axios.post('/api/all-calcs')
.then(response => this.setState({calcs: response.data}))
.catch(error => console.log(error));
}
getCalcs() {
this.listItems = this.state.calcs.map((calc, index) =>
<a key={index} href="#" className="list-group-item list-group-item-action flex-column align-items-start">
<div className="d-flex w-100 justify-content-between">
<h5 className="mb-1">{calc.h1}</h5>
<small>3 days ago</small>
</div>
<p className="mb-1">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget
risus varius blandit.</p>
<small>Donec id elit non mi porta.</small>
</a>
);
}
render() {
return (
<div>
<div className="list-group">
{this.listItems}
</div>
</div>
);
}
}
if (document.querySelector('#all-calcs')) {
ReactDOM.render(<AllCalcs />, document.querySelector('#all-calcs'));
}
I'm sure an experienced developer will understand what the problem is and tell you in a second. The point is that by / api / all-calcs we get an array with posts. They need to be written in this.state.calcs so that it can be used in the getCalcs method. Please help me find out what I am doing wrong.
Upvotes: 2
Views: 57
Reputation: 25842
The request is async, so you are setting up the list items before the data comes in. instead you should do it like this.
export default class AllCalcs extends Component {
constructor(props) {
super(props);
this.state = { calcs: [] };
}
componentDidMount() {
this.fetchData();
}
fetchData() {
axios
.post('/api/all-calcs')
.then(response => this.setState({ calcs: response.data }))
.catch(error => console.log(error));
}
getCalcs(calcs || []) {
return calcs.map((calc, index) => (
<a
key={index}
href="#"
className="list-group-item list-group-item-action flex-column align-items-start"
>
<div className="d-flex w-100 justify-content-between">
<h5 className="mb-1">{calc.h1}</h5>
<small>3 days ago</small>
</div>
<p className="mb-1">
Donec id elit non mi porta gravida at eget metus. Maecenas sed diam
eget risus varius blandit.
</p>
<small>Donec id elit non mi porta.</small>
</a>
));
}
render() {
const { calcs } = this.state
return (
<div>
<div className="list-group">{this.getCalcs(calcs)}</div>
</div>
);
}
}
Essentially what you want to do is kick off the request on componentDidMount
. And then build the list of items to render when you render. Dont put it on a variable on the class as it is no longer tied to the lifecycle of the class (you wont see updates / render cycles when you store on a property of the class like that)
Upvotes: 2