React Native Hooks: невозможно отобразить значения в return () из функции useEffect - PullRequest
0 голосов
/ 03 апреля 2020

Использование перехватчиков реагирования с базой данных Firebase в реальном времени с проектом, над которым я работаю впервые, данные извлекаются и регистрируются в консоли. НО я не могу go выйти за пределы функции useEffect для отображения значений на экране! Буду очень признателен за некоторую помощь!

videoArray необходимо поместить в FlatList, как вы можете видеть в приведенном ниже коде, videoArray регистрирует значения в консоли в функции useEffect. Однако, как только я переместил эту функцию, чтобы добавить ее в FlatList, она становится пустой, потому что значения находятся в локальной функции.

Мой вопрос заключается в том, как я могу передать значение videoArray (inEaseEffect) в 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>
    );
}

Ответы [ 3 ]

2 голосов
/ 03 апреля 2020

Похоже, что вы пытаетесь обновить State Hook (videoArray), но вы делаете это неправильно (его не следует изменять напрямую). Вместо этого используйте метод обновления setVideo, который вы создали с помощью зацепки (let [videoArray, setVideo] = useState([]);):

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);
});

Проверьте Использование зацепки с эффектом для получения дополнительной информации о том, как использовать это Speci c крюк (особенно интересен раздел Оптимизация производительности путем пропуска эффектов ).

По сути, эта функциональность аналогична аналогам вашего функционального компонента с состоянием ( React.Component или React.PureComponent ), где:

Конструктор - это единственное место, где вы должны назначить this.state напрямую. Во всех других методах вам нужно использовать this.setState ().

2 голосов
/ 03 апреля 2020

Попробуйте это:

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 голосов
/ 03 апреля 2020

Попробуйте это:

  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
    });
  }, []);
...