Korzystanie z reaktorów z bazą danych czasu rzeczywistego Firebase z projektem, nad którym pracuję po raz pierwszy, dane są pobierane i rejestrowane w konsoli. ALE nie mogę wyjść poza funkcję useEffect, aby wyświetlić wartości na ekranie! Naprawdę wdzięczny za pomoc!

VideoArray należy umieścić w FlatList, jak widać w poniższym kodzie videoArray rejestruje wartości w konsoli w funkcji useEffect. Jednak po usunięciu tej funkcji, aby dodać ją do FlatList, jest ona pusta, ponieważ wartości są w funkcji lokalnej.

Moje pytanie brzmi: w jaki sposób mogę przekazać wartość videoArray (in useEffect) do 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>
    );
}
0
dreamLand70 3 kwiecień 2020, 21:22

3 odpowiedzi

Najlepsza odpowiedź

Spróbuj tego:

  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
    });
  }, []);
2
awran5 3 kwiecień 2020, 18:58

Spróbuj tego:

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
Max Gram 3 kwiecień 2020, 19:43

Wygląda na to, że próbujesz zaktualizować hook stanu (videoArray), ale robisz to w niewłaściwy sposób (nie należy go modyfikować bezpośrednio). Zamiast tego użyj metody aktualizacji setVideo, którą utworzyłeś za pomocą hooka (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);
});

Zapoznaj się z Using the Effect hook, aby uzyskać więcej informacji o tym, jak używać tego konkretnego zaczepu ( sekcja Optymalizacja wydajności przez pomijanie efektów może być szczególnie interesująca).

Zasadniczo ta funkcja jest podobna do stanowych odpowiedników komponentu funkcjonalnego (React.Component lub React.PureComponent), gdzie:

Konstruktor to jedyne miejsce, w którym należy bezpośrednio przypisać this.state. We wszystkich innych metodach należy zamiast tego użyć this.setState ().

2
Theodor Amariucai 3 kwiecień 2020, 19:06