electro7912 electro7912 - 5 months ago 40
React JSX Question

Setting fetched data from API in state won't work

I'm trying to build a news/article website for education purposes using Django and ReactJS.

Currently, I've created an article model in Django and set up an API for ReactJS to talk to. Every article has a headline, image, content, featured and quickreads properties. featured and quickreads are boolean values. I've successfully set up my ReactJS component to fetch all the articles however, I'm having trouble filtering the articles that have

article.featured
as true and
article.quickreads
also as true. Currently my component has three states: articles, featured and quickreads. This is how it currently looks:

class Api extends React.Component{
constructor(){
super();
this.state = {
articles: null,
featured: null,
quickreads: null
}
}
componentDidMount(){
fetch("http://127.0.0.1:8000/articles/articlesapi/").then(request => request.json()).then(response => this.setState({articles: response}))
var featured = this.state.articles.filter(article => article.featured === true)
var quickreads = this.state.articles.filter(article => article.quickreads === true)
this.setState({featured: featured, quickreads: quickreads})
}
render(){
return (
<p>Hello World</p>
)
}
}


Although the component gets all the articles it fails to update
featured
and
quickreads
. I get the following error:

Uncaught TypeError: Cannot read property 'articles' of undefined at componentDidMount (eval at <anonymous>)...


Why is this happening?

Answer Source

fetch is asynchronous, and thus articles is not set (and is null) when you try to filter it to set state. Instead, wait until the data is fetched:

fetch("http://127.0.0.1:8000/articles/articlesapi/")
  .then(request => request.json())
  .then(response => {
    this.setState({
      articles: response
      featured: response.filter(article => article.featured === true),
      quickreads: response.filter(article => article.quickreads === true)
    });
  });

And filter and set state along with setting articles after the data is fetched. I would, though, only store articles in state, and filtering when you need to do you don't end up having to sync up all the arrays to make sure they have the same data.