如何在 setState() 之后将 Firebase 数据提取到变量中?

How to extract Firebase data to variable after setState() with react?

第一次使用 React 和 firebase real-time 数据库。我很难提取数据并将其插入到 const 项中。据我了解,firebase代码是异步的,所以代码会在页面加载完成后执行。

多次检查控制台后,我看到数据加载到 const tasks 数组中。但是,当我将它放入项目数组(标题、副标题等)中时,任务 [] 中的数据不会显示。我已经查看了多种解决方案,其中 none 已经回答了我的问题。

我以为是因为item是const,改成var后问题依旧。任何形式的指导都将不胜感激。

一个小提示:使用 await 似乎对我不起作用。由于我对 firebase + react 缺乏了解,我可能会把事情搞混。

const Timelines = () => {

    const [tasks, setTasks] = useState([]);

    useEffect(() => {
        const ref = firebase.database().ref();
        const listener = ref.on('value', snapshot => {
            const fetchedTasks = [];
            snapshot.forEach(childSnapshot => {
                const key = childSnapshot.key; //using await here doesn't work. Return 'await is a reserved word error'
                const data = childSnapshot.val(); //using await here doesn't work. Return 'await is a reserved word error'
                fetchedTasks.push({ id: key, ...data });
            });
            setTasks(fetchedTasks);
        });
        return () => ref.off('value', listener);
    }, [firebase.database()]);



    const items = [{
        title: "Header" + tasks,
        cardTitle: "Title",
        //url: "http://www.history.com",
        cardSubtitle: "LA",
        cardDetailedText: ["Paragrah"],
        media: {
            type: "IMAGE",
            source: {
                url: "./images/image1.jpeg"
            }
        }
    },
        {
            title: "Title",
            cardTitle: "Title1",
            //url: "http://www.history.com",
            cardSubtitle: "LA",
            cardDetailedText: "Paragraph 1",
            media: {
                type: "IMAGE",
                source: {
                    url: "./images/img-2.jpg"
                }
            }
        },
    
    
    ]
    return (
        <div className='timeline' style={{ width: "auto", height: "auto" }}>
            <Chrono items={items}
                slideShow
                mode="VERTICAL_ALTERNATING"
                theme={{
                    primary: "#7e8083",
                    secondary: "white",
                    cardBgColor: "#00467f",
                    cardForeColor: "white",
                    titleColor: "#00467f"
                }}
                useReadMore="true" />
        </div>
        
    ) 
  };

export default Timelines;

您的问题可能是重新渲染问题。所以你可以尝试加载状态。检查我的 useEffect 和 return.

const Timelines = () => {

    const [tasks, setTasks] = useState([]);
    const [loading, setLoading] = useState(false); //<----


    useEffect(() => {
        setLoading(true) //<-----
        const ref = firebase.database().ref();
        const listener = ref.on('value', snapshot => {
            const fetchedTasks = [];
            snapshot.forEach(childSnapshot => {
                const key = childSnapshot.key; //using await here doesn't work. Return 'await is a reserved word error'
                const data = childSnapshot.val(); //using await here doesn't work. Return 'await is a reserved word error'
                fetchedTasks.push({ id: key, ...data });
            });
            setTasks(fetchedTasks);
            setLoading(false) //<---
        });
        return () => ref.off('value', listener);
    }, [firebase.database()]);



    const items = [{
        title: "Header" + tasks,
        cardTitle: "Title",
        //url: "http://www.history.com",
        cardSubtitle: "LA",
        cardDetailedText: ["Paragrah"],
        media: {
            type: "IMAGE",
            source: {
                url: "./images/image1.jpeg"
            }
        }
    },
        {
            title: "Title",
            cardTitle: "Title1",
            //url: "http://www.history.com",
            cardSubtitle: "LA",
            cardDetailedText: "Paragraph 1",
            media: {
                type: "IMAGE",
                source: {
                    url: "./images/img-2.jpg"
                }
            }
        },
    
    
    ]
    return !loading &&  (
        <div className='timeline' style={{ width: "auto", height: "auto" }}>
            <Chrono items={items}
                slideShow
                mode="VERTICAL_ALTERNATING"
                theme={{
                    primary: "#7e8083",
                    secondary: "white",
                    cardBgColor: "#00467f",
                    cardForeColor: "white",
                    titleColor: "#00467f"
                }}
                useReadMore="true" />
        </div>
        
    ) 
  };

export default Timelines;

谢谢

Gökhan Geyik 所说的解决方案是正确的。但是我不得不稍微调整我的代码,因为我的 Firebase 数据库结构不同。问题是,重新渲染!

 useEffect(() => {
        setLoading(true)
        const ref = firebase.database().ref('Overview/events');
        const listener = ref.on('value', snapshot => {
            const fetchedTasks = [];
            const data = snapshot.val();
            fetchedTasks.push(data);
            setTasks(fetchedTasks);
            setLoading(false)
        });
        return () => ref.off('value', listener);
    }, [firebase.database()]);

return !loading && ( 
   ....
)

这很有效。非常感谢 Gökhan Geyik 的正确方向!