iphonic
iphonic

Reputation: 12719

React - render() not called with setState with axios

I am trying to fetch an array of movies and after it fetches the list it updates the state and the list should render, but the problem is the render method never calls from inside the axios callback, here is my code below

export default class Movies extends Component {
    constructor(props){
      super(props);

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

    componentDidMount(){

      axios.get('URL')
            .then(response => {
              this.setState({movies:response.data});
              console.log("Movies",this.state);// I get the values here see screenshot..

      });
  }

  render(){
    return(
      <div className="row">
        <div className="col-md-3">
          <MovieList movies={this.state.movies}/>
        </div>
        <div className="col-md-6">Movie Details</div>
      </div>
    );
  }
} 

As you can see the code above, in function componentDidMount in the axios callback I am setting the response values to the state, but it doesn't call the render after doing it, the block does execute well as I get the log properly see screenshot below enter image description here

I am not understanding why it doesn't call render() ? I have tried couple of solutions available but none works for me, if I hardcode the videos array in default state it works fine, please help if anyone know the solution.

Update(Adding MovieList Code)

class ListItem extends Component {
  render(){
    return(
      <li className="list-group-item">{this.props.moviename}</li>
    );
  }
}

export default class MoviesList extends Component {
  constructor(props) {
    super(props);
    console.log("Props",props);
    this.state={movies:props.movies};
  }

  renderList(){

    const items=this.state.movies.map((movie) => <ListItem moviename={movie.name} key={movie.name}/>);

    return items;
  }

  render(){
    return(
      <ul className="list-group">
        <li className="list-group-item"><h3>Movies</h3></li>
        {this.renderList()}
      </ul>
    );
  }
}

Thanks.

Upvotes: 1

Views: 821

Answers (3)

Stas Parshin
Stas Parshin

Reputation: 1673

You should consider making your MoviesList stateless:

export default class MoviesList extends Component {

  constructor(props) {
    super(props);
    console.log("Props",props);
    //If your component won't alter movies list by itself - there's no point to manage its "state"
    //this.state={movies:props.movies};
  }

  renderList(){
    //Use props here instead
    const items=this.props.movies.map((movie) => <ListItem moviename={movie.name} key={movie.name}/>);
    return items;
  }

  render(){
    return(
      <ul className="list-group">
        <li className="list-group-item"><h3>Movies</h3></li>
        {this.renderList()}
      </ul>
    );
  }
}

Generally, you should strive to dumbing-down your components whenever possible.

Upvotes: 1

Working Pig
Working Pig

Reputation: 194

The problem you are getting is in ListItem Component. In order to get it work you need to work with componentWillReceiveProps

In this case, construct is called only once Because of that your component won't update. You need to use function componentWillReceiveProps , this function will run every time component receive new data.

Example:

componentwillreceiveprops(nextProps){
 this.setState({
   movies: nextProps.movies
})
}

Upvotes: 2

vic
vic

Reputation: 96

Did you added componentWillReceiveProps in MovieList?

Upvotes: 1

Related Questions