typescript 如果我的上下文用于从Firebase获取数据的自定义钩子,为什么React会抛出错误?

bvjxkvbb  于 2023-01-21  发布在  TypeScript
关注(0)|答案(1)|浏览(67)

我试图将数据提取移到组件文件的自定义钩子上,以便更好地组织代码,但当与上下文结合使用时,钩子不起作用。
这是我的AuthContext.tsx文件

import React, { createContext, useEffect, useState } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from '../firebase.config';

export const UserContext = createContext<any>({});

export const AuthContextProvider = ({ children }: any) => {
    const [currentUser, setCurrentUser] = useState<unknown | null>({});

    useEffect(() => {
        const unsub = onAuthStateChanged(auth, (user) => {
            setCurrentUser(user);
        });

        return () => {
            unsub();
        };
    }, []);

     return <UserContext.Provider value={{ currentUser }}>{children}</UserContext.Provider>;
};

这是我的useRooms.ts文件(我的钩子)

import * as React from 'react';
import { collection, query, where, getDocs, QueryDocumentSnapshot, DocumentData } from 'firebase/firestore';

import { db } from '../firebase.config';
import { UserContext } from '../context/AuthContext';
import { RoomsResult } from './types';

export default function useRooms(): RoomsResult {
const [userRooms, setUserRooms] = React.useState<string[] | null>(null);
const [isLoading, setIsLoading] = React.useState(true);

const { currentUser } = React.useContext(UserContext);

const userRoomsQuery = query(collection(db, 'rooms'), where('user', 'array-contains', currentUser.uid));

const fetchUserRoomsData = async () => {
    setIsLoading(true);
    const userRoomsDocs = await getDocs(userRoomsQuery);
    setUserRooms(userRoomsDocs.docs.map((doc: QueryDocumentSnapshot<DocumentData>) => doc.id));
    setIsLoading(false);
};

console.log(userRooms);

return { rooms: userRooms, loading: isLoading, fetchUserRoomsData };
}

我收到的错误是:

至于在错误中看到的那些文件名,它们都来自我的App.tsx文件

import React, { useContext } from 'react';
import { BrowserRouter, Routes, Route, Navigate } from 'react-router-dom';
import { UserContext } from './context/AuthContext';
import { SignUpForm, LogInForm, ChatRooms } from './components/exporter';

type Styles = {
    wrapper: string;
};

function App() {
    const styles: Styles = {
         wrapper:
            'bg-purple-200 h-[100vh] w-[100vw] grid grid-cols [minmax(100px,_250px)_1fr_minmax(150px,_250px)] grid-rows-[85%_minmax(50px,_350px)] absolute',
    };

    const { currentUser } = useContext(UserContext);

    const ProtectedRoute = ({ children }: any) => {
        if (!currentUser) {
            return <Navigate to="/login" />;
        } else return children;
    };

    return (
        <BrowserRouter>
            <Routes>
                <Route
                    path="/"
                    element={
                        <ProtectedRoute>
                            <div id="portal-container">
                                <ChatRooms />
                            </div>
                        </ProtectedRoute>
                    }
                ></Route>
                <Route path="login" element={<LogInForm />} />
                <Route path="signup" element={<SignUpForm />} />
                <Route path="*" element={<Navigate to="/" replace />} />
            </Routes>
        </BrowserRouter>
    );
}

export default App;

只要我不使用useRooms.ts文件中的const { currentUser } = React.useContext(UserContext);行,钩子本身就可以工作,但一旦我使用了,我就会在picutre中收到错误。**我将自定义钩子useRooms的使用放在我的组件中,可以看到它呈现为App.tsx中最嵌套的元素。**是否知道是什么导致了这种情况,为什么?

slmsl1lt

slmsl1lt1#

我设法通过将AuthContextProvider中currentUser的默认状态设置为null而不是{}来修复此问题
不幸的是,这使得当我刷新我的网页时,它现在忘记了登录的用户。但这可能是预期的行为,直到我检查Firebase Auth文档。

相关问题