1

I need to load article from DB and set it like a component's state. Then this article should be shown on the page. But when I try to do this, there is an error that the value of loaded article's state is undefined. So, I think that the problem occures because the loading data function is called after the component's render. How can I call this function before rendering and properly show state's value?

import React from 'react';
import axios from 'axios';  
import { connect } from 'react-redux';
import { withRouter } from "react-router";

class ArticlePage extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      article: null,
    }
  }

  componentDidMount() {
    const { onLoad } = this.props;

    // gets full list of articles
    axios('http://localhost:8080/api/articles')
      .then((res) => onLoad(res.data))
  }

  getArticle() {
    // gets current article
    // ...
  }

  render() {

    this.getArticle();
    const { article } = this.state;

    return (
      <div>
      <h1>
        {article.title}
      </h1>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  articles: state.home.articles,
});

const mapDispatchToProps = dispatch => ({
  onLoad: data => dispatch({ type: 'HOME_PAGE_LOADED', data }),
  onDelete: id => dispatch({ type: 'DELETE_ARTICLE', id }),
  setEdit: article => dispatch({ type: 'SET_EDIT', article }),
});

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(ArticlePage));
Amphyx
  • 669
  • 4
  • 12
  • 24

3 Answers3

0

You Should use componentWillMount

async componentWillMount() {
    const {onLoad} = this.props;

    // gets full list of articles
    try {
        const res = await axios('http://localhost:8080/api/articles');
        onLoad(res.data);
    } catch (e) {
        console.log(e, "error");
    }

}
Akshay Bande
  • 2,491
  • 2
  • 12
  • 29
0

You're doing nothing wrong. You just need to perform a check before you render the component so that you can avoid initial null value:

{ article && article.title }

Alternatively, you can also define empty value:

this.state = {
  article: {
    title: ''
  }
}

Ah, also pointed out by @gdh, you're making function call inside the render hook. Instead you should call that function inside the componentDidMount hook.

Bhojendra Rauniyar
  • 83,432
  • 35
  • 168
  • 231
0

You are not setting state for article so it seems that you are obtaining the value of article in getArticles. You are also calling getArticles in render which will cause the re-render which will lead you to infinite loop.

In addition to making checks such as { article && article.title },

So, in componentDidMount, call the getArticles function after you do the fetch.

componentDidMount() {
    const { onLoad } = this.props;

    // gets full list of articles
    axios('http://localhost:8080/api/articles')
      .then((res) => {
       onLoad(res.data);
       // call getArticles here.
       getArticles() {
        // code ...
       }
      })
  }

gdh
  • 13,114
  • 2
  • 16
  • 28