为什么一个数组填充了数据而另一个数组不在控制台中:[ ] 和 [ {..} {..} ] 给定相同的数据集?

Why is one array populated with data but the other isn't in the console: [ ] and [ {..} {..} ] given identical datasets?

所以我做了一个有趣的测试,因为我的数据没有填充到我的 FlatList React Native 元素中。我制作了两个状态变量:realListfakeList:

state = { 
    realList: [],
    fakeList: [],
}

然后在 componentWillMount 中,下面的函数是 运行,它填充两个名为 realfake 的数组。一个使用从 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))