Teoman Tıngır
Teoman Tıngır

Reputation: 2866

Component is not re-rendering after state changed

I'm trying to fetch videos from youtube and display on browser.. I'm able to get videos and update state property. ( checked with console log)

But SearchResults component is not re-rendering when I update the state property. Here is my component

class Application extends React.Component {

    state = {videos: []};

    handleFormSubmit = async term => {
        const res = await youtubeApi.get("search", {
            params: {q: term}
        });

        this.setState({videos: res.data.items})
    };

    render() {
        return (
            <div className="container">
                <SearchForm onFormSubmit={this.handleFormSubmit}/>
                <SearchResults videos={this.state.videos}/>
            </div>
        )
    }
}

SearchResults component

class SearchResults extends React.Component {

    state = {featured: null, suggested: []};

    componentDidMount() {
        if (this.props.videos.length > 0)
            this.setState({featured: this.props.videos[0].id.videoId});

        if (this.props.videos.length > 1)
            this.setState({suggested: this.props.videos.slice(1)});
    }

    handleSidebarVideoClick = id => {
        this.setState({featured: id})
    };

    render() {
        return (
            <div className="row">
                <div className="col-md-8">
                    <Video video={this.state.featured}/>
                </div>
                <div className="col-md-4">
                    <Sidebar videos={this.state.suggested} onSidebarVideoClick={this.handleSidebarVideoClick}/>
                </div>
            </div>
        )
    }
}

Upvotes: 0

Views: 67

Answers (2)

maudev
maudev

Reputation: 1101

You need to have getDerivedStateFromProps() in your SearchResults component in order to expect a new props value when it changes on parent component. ComponentDidMount is called once the component is mounted, not when it receives prop values when it changes every time.

So you should have something like this:

static getDerivedStateFromProps(nextProps) {
    if (nextProps.videos.length > 0) {
      return {
        featured: nextProps.videos[0].id.videoId
      };
    }
    if (nextProps.videos.length > 1) {
      return {
        suggested: nextProps.videos.slice(1)
      };
    }
    return null;
  }

Ref: https://reactjs.org/docs/react-component.html#static-getderivedstatefromprops

Upvotes: 1

Randy Casburn
Randy Casburn

Reputation: 14165

It is unlikely you checked the component's state property. You most likely checked this.state which does get updated. The question is what is this.

There is no evidence you bound your event handlers to the component as recommended in the dev guide. So the keyword this doesn't reflect the Component, it reflects the DOM element receiving the event.

To test this, console log the value of this in you event handlers.

To fix:

this.handleFormSubmit = this.handleFormSubmit.bind(this);
this.handleSidebarVideoClick = this.handleSidebarVideoClick.bind(this);

in their respective classes constructors.

Ref: https://reactjs.org/docs/handling-events.html

Upvotes: 0

Related Questions