代码之家  ›  专栏  ›  技术社区  ›  Min Htet Oo

无法将回调函数直接添加到jsx子元素的click事件中

  •  0
  • Min Htet Oo  · 技术社区  · 6 年前

    我正在尝试构建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;
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Aanchal1103 user2472759    6 年前

    添加括号时 () 对于一个函数,它被执行。所以,这条线

    onClick={onVideoSelect(video)}

    使函数在遇到此行时立即执行。在这个函数中,您调用的是setState,因此状态会更新并触发Render方法,然后该方法再次执行 onVideoSelect 方法和它形成一个循环。 您需要传递给onclick,一个函数的引用。当click事件发生时,onclick执行传递给它的函数。

    onClick={() => onVideoSelect(video)}