反应 UseContext 最新值
React UseContext latest value
我有一个用于身份验证的 React firebase 应用程序。我将 Usecontext 与 setState 一起使用。你可以看到下面的代码。当用户首次登录或注册时,此方案运行良好。但是,一旦我重新加载,上下文值就会瞬间为 null,然后它会从 firebase 的 auth 获取最新值。这导致我无法访问私有路由,即使用户已登录。
AuthContext.js 文件
import React, { useContext, useEffect, useState } from "react";
import { firebaseAuth } from "../firebase";
import {
createUserWithEmailAndPassword,
signOut,
signInWithEmailAndPassword,
onAuthStateChanged,
} from "firebase/auth";
const AuthContext = React.createContext();
export const useAuth = () => {
return useContext(AuthContext);
};
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState(null);
console.log("Auth Context User:", user);
useEffect(() => {
const unsub = onAuthStateChanged(firebaseAuth, (user) => {
setUser(user);
});
return unsub();
}, [user]);
function SignUp(email, password) {
return createUserWithEmailAndPassword(firebaseAuth, email, password);
}
function Logout() {
return signOut(firebaseAuth);
}
function Login(email, password) {
return signInWithEmailAndPassword(firebaseAuth, email, password);
}
const value = {
logout: Logout,
signup: SignUp,
login: Login,
user,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
App.js 文件
import Header from "./components/Header";
import Login from "./components/Login";
import NotFound from "./components/NotFound";
import Signup from "./components/Signup";
import Home from "./components/Home";
import AuthGuard from "./guard/AuthGuard";
import ErrorComp from "./components/ErrorComp";
import { AuthContextProvider } from "./context/AuthContext";
import { GlobalStyles } from "./styledComps/Global";
import { Route, Routes } from "react-router-dom";
function App() {
return (
<>
<GlobalStyles />
<AuthContextProvider>
<Header />
<ErrorComp>
<Routes>
<Route path="" element={<Login />} exact />
<Route path="/signup" element={<Signup />} />
<Route
path="/home"
element={
<AuthGuard>
<Home />
</AuthGuard>
}
/>
<Route path="*" element={<NotFound />} />
</Routes>
</ErrorComp>
</AuthContextProvider>
</>
);
}
export default App;
AuthGuard.js 文件
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
const AuthGuard = ({ children }) => {
let { user } = useAuth();
let location = useLocation();
console.log("user", user);
if (!user) {
return <Navigate to="/" state={{ from: location }} />;
}
return children;
};
export default AuthGuard;
由于在重新加载时必须重新获取用户(这需要一些时间),因此用户对象将 null
直到进程完成。你可以简单地尝试 guard 你的渲染
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState(null);
console.log("Auth Context User:", user);
useEffect(() => {
const unsub = onAuthStateChanged(firebaseAuth, (user) => {
setUser(user);
});
return unsub();
}, [user]);
function SignUp(email, password) {
return createUserWithEmailAndPassword(firebaseAuth, email, password);
}
function Logout() {
return signOut(firebaseAuth);
}
function Login(email, password) {
return signInWithEmailAndPassword(firebaseAuth, email, password);
}
const value = {
logout: Logout,
signup: SignUp,
login: Login,
user,
};
if ( user !== null ) {
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
return <>Loading ... or render eg. a spinner</>
};
我有一个用于身份验证的 React firebase 应用程序。我将 Usecontext 与 setState 一起使用。你可以看到下面的代码。当用户首次登录或注册时,此方案运行良好。但是,一旦我重新加载,上下文值就会瞬间为 null,然后它会从 firebase 的 auth 获取最新值。这导致我无法访问私有路由,即使用户已登录。
AuthContext.js 文件
import React, { useContext, useEffect, useState } from "react";
import { firebaseAuth } from "../firebase";
import {
createUserWithEmailAndPassword,
signOut,
signInWithEmailAndPassword,
onAuthStateChanged,
} from "firebase/auth";
const AuthContext = React.createContext();
export const useAuth = () => {
return useContext(AuthContext);
};
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState(null);
console.log("Auth Context User:", user);
useEffect(() => {
const unsub = onAuthStateChanged(firebaseAuth, (user) => {
setUser(user);
});
return unsub();
}, [user]);
function SignUp(email, password) {
return createUserWithEmailAndPassword(firebaseAuth, email, password);
}
function Logout() {
return signOut(firebaseAuth);
}
function Login(email, password) {
return signInWithEmailAndPassword(firebaseAuth, email, password);
}
const value = {
logout: Logout,
signup: SignUp,
login: Login,
user,
};
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};
App.js 文件
import Header from "./components/Header";
import Login from "./components/Login";
import NotFound from "./components/NotFound";
import Signup from "./components/Signup";
import Home from "./components/Home";
import AuthGuard from "./guard/AuthGuard";
import ErrorComp from "./components/ErrorComp";
import { AuthContextProvider } from "./context/AuthContext";
import { GlobalStyles } from "./styledComps/Global";
import { Route, Routes } from "react-router-dom";
function App() {
return (
<>
<GlobalStyles />
<AuthContextProvider>
<Header />
<ErrorComp>
<Routes>
<Route path="" element={<Login />} exact />
<Route path="/signup" element={<Signup />} />
<Route
path="/home"
element={
<AuthGuard>
<Home />
</AuthGuard>
}
/>
<Route path="*" element={<NotFound />} />
</Routes>
</ErrorComp>
</AuthContextProvider>
</>
);
}
export default App;
AuthGuard.js 文件
import React from "react";
import { Navigate, useLocation } from "react-router-dom";
import { useAuth } from "../context/AuthContext";
const AuthGuard = ({ children }) => {
let { user } = useAuth();
let location = useLocation();
console.log("user", user);
if (!user) {
return <Navigate to="/" state={{ from: location }} />;
}
return children;
};
export default AuthGuard;
由于在重新加载时必须重新获取用户(这需要一些时间),因此用户对象将 null
直到进程完成。你可以简单地尝试 guard 你的渲染
export const AuthContextProvider = ({ children }) => {
const [user, setUser] = useState(null);
console.log("Auth Context User:", user);
useEffect(() => {
const unsub = onAuthStateChanged(firebaseAuth, (user) => {
setUser(user);
});
return unsub();
}, [user]);
function SignUp(email, password) {
return createUserWithEmailAndPassword(firebaseAuth, email, password);
}
function Logout() {
return signOut(firebaseAuth);
}
function Login(email, password) {
return signInWithEmailAndPassword(firebaseAuth, email, password);
}
const value = {
logout: Logout,
signup: SignUp,
login: Login,
user,
};
if ( user !== null ) {
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
}
return <>Loading ... or render eg. a spinner</>
};