为什么一个数组填充了数据而另一个数组不在控制台中:[ ] 和 [ {..} {..} ] 给定相同的数据集?
Why is one array populated with data but the other isn't in the console: [ ] and [ {..} {..} ] given identical datasets?
所以我做了一个有趣的测试,因为我的数据没有填充到我的 FlatList
React Native 元素中。我制作了两个状态变量:realList
和 fakeList
:
state = {
realList: [],
fakeList: [],
}
然后在 componentWillMount
中,下面的函数是 运行,它填充两个名为 real
和 fake
的数组。一个使用从 Firebase 提取的数据,另一个使用 SAME 数组信息进行硬编码:
listenForMusic = () => {
var dataRef = database.ref("music");
let real = [];
let fake = [];
dataRef.orderByChild("date").on('child_added', (snap) => {
var url = snap.val().youtubeURL;
var vidTitle = snap.val().title;
var thumb = snap.val().thumbnail;
real.push({
videoURL: url,
title: vidTitle,
thumbnail: thumb
});
});
fake.push({videoURL: "https://youtu.be/AHukwv_VX9A", title: "MISSIO - Everybody Gets High (Audio)", thumbnail: "https://i.ytimg.com/vi/AHukwv_VX9A/hqdefault.jpg"}, {videoURL: "https://youtu.be/G-yWpz0xkWY", title: "SMNM - Million ft. Compulsive", thumbnail: "https://i.ytimg.com/vi/G-yWpz0xkWY/hqdefault.jpg"});
this.setState({
realList: real,
fakeList: fake
});
}
然后我 console.log
渲染函数后的两个数组:
render() {
console.log("Actual", this.state.realList);
console.log("Fake", this.state.fakeList);
return (
<View>
<FlatList
data={this.state.fakeList}
renderItem={({item}) => <Text>{item.videoURL}</Text>}
/>
</View>
);
}
我看到了这个:
并同时打开:
所以我的问题是,为什么 "real" 数组看起来是空的,但内部仍然填充了数据,而 "fake" 数组显示它在其中包含两个对象,甚至在我们采取看看里面??
在我的 FlatList 中,如果我使用我的 fakeList 数据,我可以在屏幕上显示数据,但是如果我使用我的 realList,我的屏幕上什么也没有显示。
编辑:添加完整代码以供参考:
class VideoFeed extends React.Component {
state = {
itemList: [],
}
componentDidMount() {
this.listenForMusic();
}
listenForMusic = () => {
var dataRef = database.ref("music");
let items = [];
dataRef.orderByChild("date").on('child_added', (snap) => {
items.push({
videoURL: snap.val().youtubeURL,
title: snap.val().title,
thumbnail: snap.val().thumbnail
});
});
this.setState({ itemList: items })
}
_renderVideoItem = ({item}) => (
<TouchableWithoutFeedback
onPress={Actions.Submit}
>
<View style={styles.mediaContainer}>
<Image
source={{uri: item.thumbnail }}
style={styles.mediaThumbnail}
/>
<View style={styles.mediaMetaContainer}>
<View style={styles.topMetaContainer}>
<Text style={styles.mediaTitle}>
{item.title}
</Text>
<Text style={styles.sharedByUser}>
UNCVRD
</Text>
</View>
<View style={styles.bottomMetaContainer}>
<Icon
name='youtube-play'
type='material-community'
color='#ff0000'
size={16}
/>
<View style={styles.bottomRightContainer}>
<Icon
name='thumb-up'
size={12}
color='#aaa'
/>
<Text style={styles.metaLikeCounter}>
16
</Text>
</View>
</View>
</View>
</View>
</TouchableWithoutFeedback>
);
render() {
console.log(this.state.itemList); // this list is populated
return (
<View>
<FlatList
data={this.state.itemList}
renderItem={({item}) => {
console.log('item in render --> ', item); return (<Text>{item.videoURL}</Text>) }}
/>
</View>
);
}
}
当您更详细地检查控制台日志中的对象时,您的控制台将对该对象进行新的查找。所以在你的情况下发生的是,在你的控制台日志中,数组是空的,但很快就会被填充。当您检查它时,您将看到检查时内存中存在的对象。
不建议在 componentWillMount 中执行异步操作(您会错过重新渲染),最好将其移至 componentDidMount。
编辑:
由于您希望组件在 Firebase 数据更改时自动更新,因此最好的方法是在 React class 中使用 属性 来保存对 Firebase 数据的引用。有关具体如何执行此操作的更多信息,请参阅 here。检查 实时数据库侦听器 部分。
class VideoFeed extends React.Component {
constructor(props) {
super(props);
this.state = {itemList: []};
this.realList = firebaseApp.database().ref(); // create property
}
componentDidMount() {
this.listenForMusic(this.realList); // pass property to listener method
}
listenForMusic = (list) => { // listener method
let items = [];
list.orderByChild("date").on('child_added', (snap) => {
items.push({
videoURL: snap.val().youtubeURL,
title: snap.val().title,
thumbnail: snap.val().thumbnail
});
this.setState({ itemList: items }); // update state
});
}
// rest of component code ...
}
控制台window 保存对象引用。执行第一个console.log语句时real为空。到你展开的时候。事件已经触发。您的数组不再为空。您可以在控制台中对此进行测试:
let real = [];
let fake = [1, 2];
console.log(real, fake);
setTimeout(() => real.push(9))
所以我做了一个有趣的测试,因为我的数据没有填充到我的 FlatList
React Native 元素中。我制作了两个状态变量:realList
和 fakeList
:
state = {
realList: [],
fakeList: [],
}
然后在 componentWillMount
中,下面的函数是 运行,它填充两个名为 real
和 fake
的数组。一个使用从 Firebase 提取的数据,另一个使用 SAME 数组信息进行硬编码:
listenForMusic = () => {
var dataRef = database.ref("music");
let real = [];
let fake = [];
dataRef.orderByChild("date").on('child_added', (snap) => {
var url = snap.val().youtubeURL;
var vidTitle = snap.val().title;
var thumb = snap.val().thumbnail;
real.push({
videoURL: url,
title: vidTitle,
thumbnail: thumb
});
});
fake.push({videoURL: "https://youtu.be/AHukwv_VX9A", title: "MISSIO - Everybody Gets High (Audio)", thumbnail: "https://i.ytimg.com/vi/AHukwv_VX9A/hqdefault.jpg"}, {videoURL: "https://youtu.be/G-yWpz0xkWY", title: "SMNM - Million ft. Compulsive", thumbnail: "https://i.ytimg.com/vi/G-yWpz0xkWY/hqdefault.jpg"});
this.setState({
realList: real,
fakeList: fake
});
}
然后我 console.log
渲染函数后的两个数组:
render() {
console.log("Actual", this.state.realList);
console.log("Fake", this.state.fakeList);
return (
<View>
<FlatList
data={this.state.fakeList}
renderItem={({item}) => <Text>{item.videoURL}</Text>}
/>
</View>
);
}
我看到了这个:
并同时打开:
所以我的问题是,为什么 "real" 数组看起来是空的,但内部仍然填充了数据,而 "fake" 数组显示它在其中包含两个对象,甚至在我们采取看看里面??
在我的 FlatList 中,如果我使用我的 fakeList 数据,我可以在屏幕上显示数据,但是如果我使用我的 realList,我的屏幕上什么也没有显示。
编辑:添加完整代码以供参考:
class VideoFeed extends React.Component {
state = {
itemList: [],
}
componentDidMount() {
this.listenForMusic();
}
listenForMusic = () => {
var dataRef = database.ref("music");
let items = [];
dataRef.orderByChild("date").on('child_added', (snap) => {
items.push({
videoURL: snap.val().youtubeURL,
title: snap.val().title,
thumbnail: snap.val().thumbnail
});
});
this.setState({ itemList: items })
}
_renderVideoItem = ({item}) => (
<TouchableWithoutFeedback
onPress={Actions.Submit}
>
<View style={styles.mediaContainer}>
<Image
source={{uri: item.thumbnail }}
style={styles.mediaThumbnail}
/>
<View style={styles.mediaMetaContainer}>
<View style={styles.topMetaContainer}>
<Text style={styles.mediaTitle}>
{item.title}
</Text>
<Text style={styles.sharedByUser}>
UNCVRD
</Text>
</View>
<View style={styles.bottomMetaContainer}>
<Icon
name='youtube-play'
type='material-community'
color='#ff0000'
size={16}
/>
<View style={styles.bottomRightContainer}>
<Icon
name='thumb-up'
size={12}
color='#aaa'
/>
<Text style={styles.metaLikeCounter}>
16
</Text>
</View>
</View>
</View>
</View>
</TouchableWithoutFeedback>
);
render() {
console.log(this.state.itemList); // this list is populated
return (
<View>
<FlatList
data={this.state.itemList}
renderItem={({item}) => {
console.log('item in render --> ', item); return (<Text>{item.videoURL}</Text>) }}
/>
</View>
);
}
}
当您更详细地检查控制台日志中的对象时,您的控制台将对该对象进行新的查找。所以在你的情况下发生的是,在你的控制台日志中,数组是空的,但很快就会被填充。当您检查它时,您将看到检查时内存中存在的对象。
不建议在 componentWillMount 中执行异步操作(您会错过重新渲染),最好将其移至 componentDidMount。
编辑: 由于您希望组件在 Firebase 数据更改时自动更新,因此最好的方法是在 React class 中使用 属性 来保存对 Firebase 数据的引用。有关具体如何执行此操作的更多信息,请参阅 here。检查 实时数据库侦听器 部分。
class VideoFeed extends React.Component {
constructor(props) {
super(props);
this.state = {itemList: []};
this.realList = firebaseApp.database().ref(); // create property
}
componentDidMount() {
this.listenForMusic(this.realList); // pass property to listener method
}
listenForMusic = (list) => { // listener method
let items = [];
list.orderByChild("date").on('child_added', (snap) => {
items.push({
videoURL: snap.val().youtubeURL,
title: snap.val().title,
thumbnail: snap.val().thumbnail
});
this.setState({ itemList: items }); // update state
});
}
// rest of component code ...
}
控制台window 保存对象引用。执行第一个console.log语句时real为空。到你展开的时候。事件已经触发。您的数组不再为空。您可以在控制台中对此进行测试:
let real = [];
let fake = [1, 2];
console.log(real, fake);
setTimeout(() => real.push(9))