Reputation: 13
I am not able to get the data out of state and apply the map function on it. I keep getting the
TypeError: Cannot read property 'financials' of null.
axios gets the following object, {symbol: "AAPL", financials: Array(4)}, thats why i'm using this.state.financials.financials
class Fundamentals extends Component {
state = {
financials: null,
headers: null
};
async componentDidMount() {
console.log("componentDidMOunt");
await axios
.get("https://api.iextrading.com/1.0/stock/aapl/financials?period=annual")
.then(res => {
const financials = res.data;
this.setState({ financials });
console.log(financials);
});
console.log("componentDidMount finished setting the data for the table");
}
render() {
// const headers = this.getHeaders1();
return (
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
<Card>
{this.state.financials.financials.map(items => items)} <-- i want to get the data out of state and later put it into a table.
</Card>
</GridItem>
</GridContainer>
);
}
}
Upvotes: 1
Views: 1288
Reputation: 113
That error is because React tries to render before your API call completes, in which case this.state.financials
still has its initial null
value assigned to it.
Change the default value of financials as mentioned below
state = {
financials: { financials: [] },
headers: null
};
So the final code looks something like
class Fundamentals extends Component {
state = {
financials: { financials: [] },
headers: null
};
async componentDidMount() {
console.log("componentDidMOunt");
await axios
.get("https://api.iextrading.com/1.0/stock/aapl/financials?period=annual")
.then(res => {
const financials = res.data;
this.setState({ financials });
console.log(financials);
});
console.log("componentDidMount finished setting the data for the table");
}
render() {
// const headers = this.getHeaders1();
return (
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
<Card>
{this.state.financials.financials.map(items => items)} <-- i want to get the data out of state and later put it into a table.
</Card>
</GridItem>
</GridContainer>
);
}
}
Upvotes: 1
Reputation: 622
Add a check before you actually render the data.
class Fundamentals extends Component {
state = {
financials: null,
headers: null
};
async componentDidMount() {
console.log("componentDidMOunt");
await axios
.get("https://api.iextrading.com/1.0/stock/aapl/financials?period=annual")
.then(res => {
const financials = res.data;
this.setState({ financials });
console.log(financials);
});
console.log("componentDidMount finished setting the data for the table");
}
render() {
const { financials: { financials} } = this.state;
if(!financials || (financials && !financials.length) {
return (
<LoaderComponent />
)
}
return (
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
<Card>
{financials.map(items => items)} <-- i want to get the data out of state and later put it into a table.
</Card>
</GridItem>
</GridContainer>
);
}
}
Upvotes: 1
Reputation: 817228
The first time the component renders, this.state.financials
is null
, because you are initializing it with null
:
state = {
financials: null,
headers: null
};
And that's why you are getting that error. Here is a simple example that replicates the error:
var state = {
financials: null,
};
state.financials.financials.map(() => {});
You need to check in your render method whether the value is set, and do nothing if it isn't:
render() {
// const headers = this.getHeaders1();
if (!this.state.financials) {
return null; // or some message that the data is loading
}
return (
<GridContainer>
<GridItem xs={12} sm={12} md={12}>
<Card>
{this.state.financials.financials.map(items => items)} <-- i want to get the data out of state and later put it into a table.
</Card>
</GridItem>
</GridContainer>
);
}
Alternatively you could initialize it with {financials: []}
instead:
state = {
financials: {financials: []},
headers: null
};
Then your existing code inside render
should "work" (see below).
But that alone likely won't make your component work. You also need to actually convert the entries in this.state.financials.financials
to something that React can render. Here is an example that pulls out the date:
this.state.financials.financials.map(item => item.reportDate)
Adjust this to your needs.
Upvotes: 2