Reputation: 427
I'm new to react and I'm stuck again. I'm trying to map my array to create new array of objects inside of my child component. Here's my issue - my method componentDidMount gets executed before data came from parents props, and my state stays empty. When I'm console.loging this.props and the end of componentDidMount I receive empty array, but when I'm console.loging it on render method it gives me 4 empty arrays, then it fills in to expected 300. What I'm doing wrong?
Parent component:
import "./App.css";
import { CompanyList } from "./components/companylist/companylist.component";
import { Searchfield } from "./components/searchfield/searchfield.component";
class App extends Component {
constructor(props) {
super(props);
this.state = {
companies: [],
searchfield: "",
};
}
componentDidMount = () => {
const URL = "https://xxxxx/companies";
fetch(URL)
.then((response) => response.json())
.then((data) => this.setState({ companies: data }))
.catch((error) => {
console.error("Error", error);
});
};
render() {
const filteredCompanies = this.state.companies.filter((item) =>
item.name.toLowerCase().includes(this.state.searchfield.toLowerCase())
);
return (
<div>
<Searchfield
handleChange={(e) => this.setState({ searchfield: e.target.value })}
/>
<CompanyList companies={filteredCompanies} />
</div>
);
}
}
export default App;
Children component:
import React, { Component } from "react";
import { Company } from "../company/company.component";
export class CompanyList extends Component {
constructor(props) {
super(props);
this.state = {
newArray: [],
};
}
componentDidMount = () => {
const filledArray = this.props.companies.map((item) => {
let result;
fetch(`https://xxxxx/incomes/${item.id}`)
.then((response) => response.json())
.then((data) => {
let transactionsToFloat = data.incomes.map((item) =>
parseFloat(item.value)
);
result = transactionsToFloat.reduce((acc, num) => {
return acc + num;
}, 0);
result = Math.round(result * 100) / 100;
});
return {
id: item.id,
name: item.name,
city: item.city,
totalIncome: result,
};
});
this.setState({ newArray: filledArray });
console.log(this.props);
};
render() {
console.log(this.props);
return (
<div>
<table>
<thead>
<tr>
<th> Id </th>
<th> Name </th>
<th> City </th>
<th> Total income </th>
</tr>
</thead>
{this.props.companies.map((item) => (
<Company key={item.id} company={item} />
))}
</table>
</div>
);
}
}
Upvotes: 1
Views: 521
Reputation: 119
componentWillMount() happens before render(). componentDidMount() happens after.
This is happening because of how React works fundamentally. React is supposed to feel fast, fluent and snappy. the application should never get logged up with http requests or asynchronous code. The answer is to use the lifecycle methods to control the DOM.
What does it mean when a component mounts?
It might be helpful to understand some of the React vocabularies a little better. When a component is mounted it is being inserted into the DOM. This is when a constructor is called. componentWillMount is pretty much synonymous with a constructor and is invoked around the same time. componentDidMount will only be called once after the first render.
componentWillMount --> render --> componentDidMount
Upvotes: 1