2016-11-18 136 views
0

我按照关于如何构建React应用程序的教程,而且我遇到了一些奇怪的问题。React好像不会将道具传递给其他组件

当我尝试将某些信息传递给另一个组件时,其他组件获取props但它是空的。

在我的情况下,index.js是这样的:

import React, { Component } from 'react'; 
import ReactDOM from 'react-dom'; 
import YTSearch from 'youtube-api-search'; 

import SearchBar from './components/search_bar'; 
import VideoList from './components/video_list'; 

const API_KEY = 'AIzaSyDdvc_zComCpdqqfmwgOsZvLOwwPEabcde'; 

class App extends Component { 
    constructor (props) { 
     super (props); 

     this.state = { 
      videos : [] 
     }; 
    } 

    componentDidMount() { 
     YTSearch (
      { 
       key : API_KEY, 
       term : 'surfboards' 
      }, 
      videos => { 
       this.setState ({ videos }); 
      } 
     ); 
    } 

    render() { 
     return (
      <div> 
       <SearchBar /> 
       <VideoList videos={this.state.videos} /> 
      </div> 
     ); 
    } 
}; 

ReactDOM.render (
    <App />, 
    document.querySelector ('.container') 
); 

和我的./components/video_list.js代码是这样的:

import React, { Component } from 'react'; 

import VideoListItem from './video_list_item'; 

class VideoList extends Component { 
    constructor(props) { 
     super(props); 

     this.state = { 
      videoItems : [] 
     }; 
    } 

    componentDidMount() { 
     this.setState(
      { 
       videoItems: this.props.videos.map(
        video => { 
         console.log(video); 
         return <VideoListItem video={video} />; 
        } 
       ) 
      } 
     ) 
    } 

    render() { 
     return (
      <ul className="col-md-4 list-group">{ this.state.videoItems }</ul> 
     ); 
    } 
} 

export default VideoList; 

的代码似乎是非常strateforward,但在现实中,它有问题。

如果我尝试在index.js我得到以下输出return语句之前这一说法console.log(this.state.videos);

// Initially I get this because the API is not yet completed: 
Array[0] 
    length: 0 
    __proto__: Array[0] 

// And then, once the API Request it is completed I get this: 
Array[5] 
    0: Object 
     etag : ""5C5HHOaBSHC5ZXfkrT4ZlRCi01A/2H00YaVLWV4Xof09xk9Q8k6vlxw"" 
     id: Object 
     kind: "youtube#searchResult" 
     snippet: Object 
     __proto__: Object 
    1: Object 
    2: Object 
    3: Object 
    4: Object 
    length: 5 
    __proto__: Array[0] 

与此同时,如果我尝试console.log(props)VideoList组件我得到的constructor方法内以下输出:

Object {videos: Array[0]} 
    videos: Array[0] 
     length: 0 
     __proto__: Array[0] 
    __proto__: Object 

你知道什么是错的吗?你看到我看不到的东西吗?

+1

自从您在构造函数中记录道具后,看起来对我很正确。 React组件有一个生命周期[https://facebook.github.io/react/docs/react-component.html](https://facebook.github.io/react/docs/react-component.html)。如果您期望看到道具传递下来,那么在更新生命周期中,比如'componentWillReceiveProps()' – phoa

+0

@phoa谢谢您的回答。我要检查'componentWillReceiveProps',我会更新你:) –

+0

@phoa谢谢:)对我有用:) –

回答

1

对此 -

与此同时,如果我尝试VideoList组件我得到以下输出的构造方法内的console.log(道具):

Object {videos: Array[0]} 
    videos: Array[0] 
     length: 0 
     __proto__: Array[0] 
    __proto__: Object 

这是绝对正确的行为。

发生这种情况的原因是,在反应组件生命周期中,您的子组件将首先呈现,并且当时传递给您的子组件的道具将具有默认或空值(例如[])。

现在你的孩子得到渲染发生父渲染。

当父母被完全呈现时componentDidMount家长的方法被调用,其中你已经做了一些Ajax请求下载动态数据,在你的情况是视频列表。

你正在做这样的,这也是完全有效的 -

componentDidMount() { 
    YTSearch (
     { 
      key : API_KEY, 
      term : 'surfboards' 
     }, 
     videos => { 
      this.setState ({ videos }); 
     } 
    ); 
} 

通过ajax数据进来后,你在对描绘周期再次发生你的父组件重新设置状态。

  this.setState ({ videos }); 

现在您的孩子将收到更新的新视频列表数组。

再次呈现孩子会有视频列表。

但是,由于您已更改了父项道具并接收了新的道具,因此您需要添加新的生命周期方法。

componentWillReceiveProps 

在这里,您可以比较old propsnew props和状态设置为更新的道具。这将呈现最新更新数据的子组件。

componentWillReceiveProps(nextProps) { 
     this.setState(
      { 
       videoItems: nextProps.videos.map(
        video => { 
         console.log(video); 
         return <VideoListItem video={video} />; 
        } 
       ) 
      } 
     ) 
} 
+0

首先谢谢你的答案。一旦父组件通过Ajax获取数据,它就会再次设置它自己的新状态。在这种情况下,你不觉得它应该更新孩子吗?如果我理解得很好,一旦父元素的状态发生变化,孩子也应该更新。或者我错了? :? –

0

在 “./components/video_list.js”

相反上componentDidMount设置状态使用componentWillReceiveProps()

在index.js

OR 的

const API_KEY = 'AIzaSyDdvc_zComCpdqqfmwgOsZvLOwwPEabcde'; 

class App extends Component { 
    constructor (props) { 
     super (props); 

     this.state = { 
      videos : [] 
     }; 
    } 

    componentDidMount() { 
     YTSearch (
      { 
       key : API_KEY, 
       term : 'surfboards' 
      }, 
      videos => { 
       this.setState ({ videos }); 
      } 
     ); 
    } 

    render() { 
     const { videos } = this.state 
     return (
      <div> 
       <SearchBar /> 

       {videos.length ? 
        <VideoList videos={this.state.videos} /> 
       : null 
       } 
      </div> 
     ); 
    } 
}; 

ReactDOM.render (
    <App />, 
    document.querySelector ('.container') 
); 
相关问题