我正在尝试构建youtube克隆。我试图通过从父组件传递给子组件的回调函数来操作状态。
但问题是,我无法将回调函数直接分配给子jsx组件的click事件。
我将回调函数从父组件、应用程序传递到子组件、VideoList,然后再次传递到VideoListItem。问题在视频列表项中。如果我像这样将回调函数从app直接添加到jsx
onClick={onVideoSelect(video)}
,它会导致无限循环并抛出错误消息“uncaught error:maximum update depth exceeded”。当组件在componentwillupdate或componentdiddupdate内重复调用setstate时,可能会发生这种情况。react限制嵌套更新的数量以防止无限循环。
但是如果我像这样添加回调函数
onClick={()=> onVideoSelect(video)}
,它起作用了。我想了解为什么会发生这种错误,并以此为基础的概念。
这是我的index.js
import React ,{Component} from 'react';
import ReactDOM from 'react-dom';
import SearchBar from './components/search_bar';
import YTSearch from 'youtube-api-search';
import VideoList from './components/video_list';
import VideoDetail from './components/video_detail';
// create a new component.That should produce some html
const API_KEY = 'AIzaSyBem7NlPNdK50NStTS4MJDlXBaiRDfI1U0'
class App extends Component {
constructor(props){
super(props);
this.state = {
videos:[],
selectedVideo: null
}
YTSearch(
{ key:API_KEY , term:'spaceart'},
videos => {
console.log("Videos Download ::"+videos.length)
this.setState({
videos:videos,
selectedVideo:videos[0]
})
}
);
}
render() {
return(
<div>
<SearchBar/>
<VideoDetail video={this.state.selectedVideo} />
<VideoList onVideoSelect = { selectedVideo => this.setState({selectedVideo}) } videos={this.state.videos} />
</div>
);
}
}
ReactDOM.render(<App/>,document.querySelector('.container'));
视频列表.js
import React from 'react';
import VideoListItem from './video_list_item';
const VideoList = (props)=>{
const videoComponents = props.videos.map(
(video) => {
return <VideoListItem onVideoSelect={props.onVideoSelect} key={video.etag} video={video} />
}
)
return (
<div><ul className="col-md-4 list-group">
{videoComponents}
</ul></div>
);
}
export default VideoList;
视频列表.js
import React from 'react';
const VideoListItem = ({video,onVideoSelect}) => {
console.log("Enter video list Item");
return (
<li onClick={onVideoSelect(video)} className="list-group-item">
<div cl
1. List item
assName="video-list media">
<div className="media-left">
<img className="media-object" src={video.snippet.thumbnails.default.url } />
</div>
<div className="media-body">
<div className="media-heading">{video.snippet.title} </div>
</div>
</div>
</li>
);
}
export default VideoListItem;