我遵循了如何构建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;
代码似乎非常具有战略性,但实际上它存在问题。
如果我在console.log( this.state.videos );
的{{1}}语句之前尝试此语句return
,我会得到以下输出:
index.js
同时,如果我在// 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 )
方法中尝试constructor
,我会得到以下输出:
VideoList
你知道什么是错的吗?你看到我看不到的东西吗?
答案 0 :(得分:1)
关于这个 -
同时如果我在VideoList
组件的构造函数方法中尝试console.log(props),我会得到以下输出:
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 props
与new props
进行比较,并将状态设置为更新的道具。这将使子组件呈现最新的更新数据。
componentWillReceiveProps(nextProps) {
this.setState(
{
videoItems: nextProps.videos.map(
video => {
console.log( video );
return <VideoListItem video={video} />;
}
)
}
)
}
答案 1 :(得分:0)
在“./components/video_list.js”
中不使用 componentDidMount 设置状态,而是使用 componentWillReceiveProps()
OR 在index.js
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' )
);