Create callback to change the state
What if we have list of data in component and we want to save one of the data items in our state?
class App extends Component {
constructor(props) {
super(props);
this.state = {
videos: [],
selectedVideo: null
};
...
We have already made component that lists the data, and we have a component, which is focused on one specific data item.
// render method of App class
...
<VideoDetail video={this.state.selectedVideo}/>
<VideoList videos={this.state.videos}/>
...
To create a callback, which will refresh the state, we should embed a function declaration into the tag of the component, which represents the data list
<VideoList
onVideoSelect={selectedVideo => this.setState({selectedVideo})}
videos={this.state.videos}/>
Then, let's move to the component, which represents the data list
const VideoList = (props) => {
const videoItems = props.videos.map((video) => {
return <VideoListItem key={video.etag} video={video}/>
});
return (
<ul className="col-md-4 list-group">
{videoItems}
</ul>
);
};
Now we should pass a function to the component, which represents data item, through the attributes of the component. We are passing a callback function here.
const videoItems = props.videos.map((video) => {
return (
<VideoListItem
onVideoSelect={props.onVideoSelect}
key={video.etag}
video={video}/>
);
});
Now we move to the component, which represents the data item
const VideoListItem = ({video}) => {
console.log(video);
const imageUrl = video.snippet.thumbnails.default.url;
return (
<li className="list-group-item">
<div className="video-list media">
<div className="media-left">
<img className="media-object" src={imageUrl}/>
</div>
<div className="media-body">
<div className="media-heading">
{video.snippet.title}
</div>
</div>
</div>
</li>
);
};
As we are passing function to the props through the JSX attributes, we could declare it in the arguments of the functions, which returns this component
const VideoListItem = ({video, onVideoSelect}) => {
...
And now, we should pass the item to the function, which arrived to this component
// VideoList item
...
return (
<li onClick={() => onVideoSelect(video)} className="list-group-item">
<div className="video-list media">
...