React Firebase 读取数据导致渲染过多

React Firebase read data results in too many renders

我正在为我的 React 项目使用 Firebase 实时数据库。我尝试遵循 firebase 文档并使用“onValue()”来检索数据。这是我的代码:

export default function Home() {
    
    const {currentUser} = useAuth();
    const [userinfo,setUserinfo] = React.useState();

    const uid = currentUser.uid
    const db = getDatabase();

    onValue(ref(db,`users/${uid}`),snapshot=>{
        const data = snapshot.val();
        setUserinfo(data);
    })


    console.log(userinfo);
    
    return (
    <main id="home">
        <Hero />
    </main>
    )
}

这会导致重新渲染次数过多的错误。我不知道如何检索数据。如果我使用

onValue(ref(db,`users/${uid}`),snapshot=>{
        const data = snapshot.val();
        console.log(data);
    })

然后正确的数据将在控制台中完美打印出来。我还尝试了以下方法:

let info;
onValue(ref(db,`users/${uid}`),snapshot=>{
        const data = snapshot.val();
        info = data;
    })
console.log(info)

但信息只是未定义。我似乎无法弄清楚这里的问题。如何使用这些数据?

它抛出的错误太多 re-renders 因为你没有使用任何生命周期钩子或函数来 update/change 状态值,一旦你更新你的状态它会再次 re-render 你的整个组件然后你再次更新状态,同样的事情发生在循环中导致太多 re-renders.
因此,为避免这种情况,您需要将负责侦听来自数据库的更改和更改状态的代码放在一个块中,该块只会在特定事件或函数调用等时被调用。

对于你的情况,我建议使用 useEffect 钩子。见下面的代码 -

export default function Home() {

    const { currentUser } = useAuth();
    const [userinfo, setUserinfo] = React.useState();

    const uid = currentUser.uid
    const db = getDatabase();

    // this useEffect will get called only 
    // when component gets mounted first time
    useEffect(() => {
        // here onValue will get initialized once
        // and on db changes its callback will get invoked
        // resulting in changing your state value
        onValue(ref(db, `users/${uid}`), snapshot => {
            const data = snapshot.val();
            setUserinfo(data);
        })
        return () => {
            // this is cleanup function, will call just on component will unmount
            // you can clear your events listeners or any async calls here
        }
    }, [])

    console.log(userinfo);

    return (
        <main id="home">
            <Hero />
        </main>
    )
}

注意 - 我最近没有使用 firebase real-time 数据库,但是通过查看代码和错误我添加了这个答案,如果有任何需要更正的地方请告诉我。