Alex T
Alex T

Reputation: 3754

Passing state back to child component

I'm trying to figure out how can i properly pass state back to the child component. Currently I have list of items and everytime i click on one of the items it changes state of "selectedVideo" variable in parent component. And then I would like to add class to the item that corresponds to that state in that child component. Basically when I click on that item in that list it become highlighted because it just changed the state of parent component.

So the main parent component is here:

index.js

class App extends Component {
constructor(props) {
super(props)
this.state = {
    videos2:[],
    selectedVideo:null
 }
this.DMSearch()
}

DMSearch(term){
    fetch(`https://api.dailymotion.com/videos?fields=description,id,thumbnail_60_url,title,url,&limit=5&search=${term}`)
    .then(result => result.json())
    .then(videos2 => {
        //console.log(videos2.list[0]);
        this.setState({
           videos2: videos2.list, 
           selectedVideo: videos2.list[0]
        });
        //console.log(this.state.selectedVideo);
     });  
    }  
render () {
    const DMSearch = _.debounce((term) => { this.DMSearch(term)}, 400);
    return (
        <div>
            <SearchBar onSearchTermChange= {DMSearch}/>
            <VideoDetail video={this.state.selectedVideo}/> 
            <VideoList 
            onVideoSelect={selectedVideo=>this.setState({selectedVideo})}
            videos2={this.state.videos2}/>
        </div>
    )
}
}  

Now the child component which changes state onclick

video_list_item.js

const VideoListItem = ({video, onVideoSelect}) => {
    const imageUrl = video.thumbnail_60_url;

    return (
      <li onClick={() => onVideoSelect(video)} className="list-group-item">
        <div className="video-list media">
          <div className="media-left">
            <img className="media-obj"  src={imageUrl}/>
          </div>
          <div className="media-body">
            <div className="media-heading">{video.title}</div>
          </div>
        </div>
      </li>
    );
  };

And what I want is to add class "active" to this specific line

<li onClick={() => onVideoSelect(video)} className="list-group-item">

Based on the state of selectedVideo that changed in index.js after clicking on that component.

Also here is the code for the whole list.

video_list.js

const VideoList = (props) => {

    const videoItems = props.videos2.map((video)=>{
        return (
        <VideoListItem 
            onVideoSelect={props.onVideoSelect}
            key={video.id} 
            video={video} />
        )
    })

    return (
        <ul className="col-md-4 list-group">
            {videoItems}
        </ul>
    )
}

Upvotes: 0

Views: 40

Answers (1)

zwippie
zwippie

Reputation: 15515

You have to pass the selectedVideo state of your App to the VideoList component,

<VideoList 
  videos2={this.state.videos2}
  onVideoSelect={selectedVideo=>this.setState({selectedVideo})}
  selectedVideo={this.state.selectedVideo}
/>

which in turn passes it to each VideoListItem

const videoItems = props.videos2.map((video)=>{
    return (
      <VideoListItem 
          onVideoSelect={props.onVideoSelect}
          key={video.id} 
          video={video}
          active={video === props.selectedVideo}
      />
    )
})

so each item can compare itself to the selectedVideo and display an 'active' class if needed.

Upvotes: 1

Related Questions