【问题标题】:React Native Hooks: unable to display values in return() from useEffect functionReact Native Hooks:无法在 useEffect 函数的 return() 中显示值
【发布时间】:2020-07-15 23:49:02
【问题描述】:

在我第一次工作的项目中使用带有 firebase 实时数据库的反应钩子,正在检索数据并在控制台中记录。但是我无法移出 useEffect 函数以在屏幕上显示值!非常感谢您的帮助!

videoArray 需要放在 FlatList 中,正如您在下面的代码中看到的那样 videoArray 在控制台中的 useEffect 函数中记录值。但是,一旦我将该函数移出以将其添加到 FlatList 中,它就会为 null,因为这些值位于本地函数中。

我的问题是,我如何将 videoArray 的值(在 useEffect 中)传递到 FlatList?

import React, { useState, useEffect } from 'react'
import { FlatList, View, TouchableOpacity, Text, StyleSheet, SafeAreaView } from 'react-native';
import { Center } from '../components/Center'
import { Video } from 'expo-av';
import firebase from '../firebase'
const videoRef = firebase.database().ref('videoCollaction');

export const FeedScreen = ({ }) => {

    let [videoArray, setVideo] = useState([]);


    useEffect(() => {

        videoRef.on('value', (childSnapshot) => {
             videoArray = [];
            childSnapshot.forEach((doc) => {
                videoArray.push({
                    key: doc.key,
                    video: doc.toJSON().video,
                });
            })    
        })

        // able to log values only here 
        console.log('working:', videoArray); 

    });

        // get video uri from firebase (testing)
        // readVideo = () => {
            // var collection = firebase.database().ref("videoCollactionvideo" + "/video").orderByValue();
            // console.log('uri', collection); 
        // }



    return (
        <SafeAreaView>
            <Text>Feed Screen</Text>

            {/* null here: need values to show up here*/}
            {console.log(" test",videoArray)}

            <FlatList
                data={videoArray}
                renderItem={({ item, index }) => {
                    return (
                        <View>

                            <Text style={{ fontSize: 35, color: 'red' }}>Video:...</Text>


                            <TouchableOpacity onPress={() => console.log('pressed')}><Text style={{ color: 'blue' }}>Expand</Text></TouchableOpacity>
                        </View>
                    );
                }} keyExtractor={({ item }, index) => index.toString()}>
            </FlatList>

        </SafeAreaView>
    );
}

【问题讨论】:

    标签: javascript reactjs react-native firebase-realtime-database react-hooks


    【解决方案1】:

    试试这个:

    import React, { useState, useEffect } from 'react'
    import { FlatList, View, TouchableOpacity, Text, StyleSheet, SafeAreaView } from 'react-native';
    import { Center } from '../components/Center'
    import { Video } from 'expo-av';
    import firebase from '../firebase'
    const videoRef = firebase.database().ref('videoCollaction');
    
    
    export const FeedScreen = ({ }) => {
        let [videoArray, setVideoArray] = useState([]);
    
    
        useEffect(() => {
    
            videoRef.on('value', (childSnapshot) => {
                const newVideoArray = [];
                childSnapshot.forEach((doc) => {
                    newVideoArray.push({
                        key: doc.key,
                        video: doc.toJSON().video,
                    });
                })    
                setVideoArray(newVideoArray);
            })
    
            // able to log values only here 
            console.log('working:', videoArray); 
    
        }, []);
    
    
        console.log('State also working :) >> ', videoArray); 
    
    
        return (
            <SafeAreaView>
                <Text>Feed Screen</Text>
    
                {/* null here: need values to show up here*/}
                {console.log(" test",videoArray)}
    
                <FlatList
                    data={videoArray}
                    renderItem={({ item, index }) => {
                        return (
                            <View>
    
                                <Text style={{ fontSize: 35, color: 'red' }}>Video:...</Text>
    
    
                                <TouchableOpacity onPress={() => console.log('pressed')}><Text style={{ color: 'blue' }}>Expand</Text></TouchableOpacity>
                            </View>
                        );
                    }} keyExtractor={({ item }, index) => index.toString()}>
                </FlatList>
    
            </SafeAreaView>
        );
    }
    

    【讨论】:

      【解决方案2】:

      您似乎正在尝试更新 State Hook (videoArray),但您的操作方式错误(不应直接修改)。相反,请使用您使用 Hook (let [videoArray, setVideo] = useState([]);) 创建的 setVideo 更新方法:

      useEffect(() => {
          videoRef.on('value', (childSnapshot) => {
              newVideoArray = [];
              childSnapshot.forEach((doc) => {
                  newVideoArray.push({
                      key: doc.key,
                      video: doc.toJSON().video,
                  });
              })    
          })
      
          // able to log values only here 
          console.log('working:', newVideoArray); 
          setVideo(newVideoArray);
      });
      

      查看Using the Effect Hook,了解有关如何使用此特定挂钩的更多信息(通过跳过效果优化性能部分可能特别有趣)。

      本质上,此功能类似于功能组件的有状态对应项(React.Component 或 React.PureComponent),其中:

      构造函数是唯一应该直接分配 this.state 的地方。在所有其他方法中,您需要改用 this.setState()。

      【讨论】:

        【解决方案3】:

        试试这个:

          useEffect(() => {
            const temp = []; // temp array
            videoRef.on("value", childSnapshot => {
              childSnapshot.forEach(doc => {
                temp.push({
                  key: doc.key,
                  video: doc.toJSON().video
                });
              });
              setVideo(temp); // update state array
            });
          }, []);
        

        【讨论】:

        • 另一件事 :) 我不是 100% 确定它是如何工作的,但是你声明 temp 的方式 - 它会在保持旧值的同时获得结果那里。如果您在 .on 回调中声明它 - 那么来自 firebase 的触发器将完全覆盖列表
        猜你喜欢
        • 1970-01-01
        • 2019-10-17
        • 2019-11-17
        • 2021-02-14
        • 2020-04-09
        • 1970-01-01
        • 2021-10-26
        • 1970-01-01
        • 2020-09-02
        相关资源
        最近更新 更多