2

I have a component that loads courses from RESTful API. After the courses have been loaded state is changed and the component should render CourseCard components with the loaded data.

The problem is that when loadCourses() method changes the state of the component no CourseCard is displayed

This is code of the component:

class Courses extends Component {

  constructor() {
    super();

    this.state = {
      courses: []
    };
  }

  componentDidMount() {
    this.loadCourses(null);
  }

  render() {
    return (
      <div>
        <CourseCategoriesBar loadCourses={this.loadCourses.bind(this)} />

        <div style={{
          paddingBottom: "120px",
          marginBottom: "30px",
        }}>
          <div className="container">
            <div className="row">

              {this.state.courses.map((course, i) => {
                return (
                  <div className="col-lg-3 col-md-6 col-sm-12" key={i}>
                    <CourseCard type="e" key={i}/>
                  </div>
                );
              })}

            </div>
          </div>
        </div>
      </div>
    );
  }

  loadCourses(id) {
    if (!id) id = ""
    let url = "http://localhost:8000/api/courses/category/" + id;

    fetch(url)
      .then((response) => response.json())
      .then((response) => this.setState(response));  
  }
}
Dils Matchanov
  • 507
  • 1
  • 5
  • 19
  • Never do binding directly in render instead do it always in constructor or use arrow function – Hemadri Dasari Sep 04 '18 at 13:11
  • @Think-Twice arrow function has the same pitfall binding in the render has (creating a new function on each render) – Nick Zuber Sep 04 '18 at 13:31
  • @Nick Zuber agreed but it’s not always. The arrow function also renders only once in certain cases. Check this thread https://stackoverflow.com/questions/52031147/react-which-is-recommended-arrow-or-normal-function – Hemadri Dasari Sep 04 '18 at 13:37
  • 1
    @Think-Twice maybe we’re misunderstanding each other — an arrow function in the render method will create a new function on each render. Check the docs https://reactjs.org/docs/faq-functions.html An arrow function defined on the class level will do the trick (only render once and bind the scope) – Nick Zuber Sep 04 '18 at 13:43
  • 1
    Yes on class level it renders only once. – Hemadri Dasari Sep 04 '18 at 13:57

2 Answers2

4

I believe you are not updating state, update the state like this

fetch(url)
  .then((response) => response.json())
  .then((response) => this.setState({courses : response.data});  
Amruth
  • 5,792
  • 2
  • 28
  • 41
0

My guess would be that your fetch response is an array, not an object.

Which means you will have a state object with properties 0,1,2 etc (like any array) instead of 'courses'.

try to map your response to the courses attribute:

.then(response => this.setState({courses: response}))
Apolo
  • 3,844
  • 1
  • 21
  • 51