2016-11-18 76 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') 
); 
相關問題