React-Firebase 路由和身份验证方法
React-Firebase routing and authentication approach
我想学习firebase路由认证的正确方法,我的意思是:
function App() {
const auth = getAuth();
if (!auth) {
<Spinner />;
}
return (
<>
{auth && (
<Router>
<Routes>
<Route path='/' element={<PrivateRoute />}>
<Route index element={<Explore />} />
<Route path='/offer' element={<Offers />} />
<Route path='/profile' element={<Profile />} />
</Route>
<Route path='/sign-in' element={<SignIn />} />
<Route path='/sign-up' element={<SignUp />} />
<Route path='/forgot-password' element={<ForgotPassword />} />
</Routes>
<Navbar />
</Router>
)}
我有这个代码块,起初我以为我应该得到一个使用 onAuthStateChanged 的 useAuth 钩子,但我意识到来自 getAuth 的这个 auth 变量的工作方式有点相同,所以为什么不使用它而不是钩子呢?
我的 PrivateRoute 看起来像这样:
function PrivateRoute() {
const currentUser = getAuth().currentUser;
return currentUser ? <Outlet /> : <Navigate to='/sign-in' />;
}
问题是一旦应用挂载,由于没有应用级别的状态,它保持不变。
然后,如果我尝试注销并在路由中添加一些逻辑,比如如果用户存在,则不允许路由到注册或登录,它不起作用。
如果我使用 redux 或 context API,我会在登录、注销、注册时分派,但如果没有它们,处理这种路由的正确设置是什么?
一段时间后,我才弄清楚如何做我需要做的事情,所以我post在这里,以防万一有人也遇到这个问题并寻求帮助。
如果你不使用 redux 或 context api 并且仍然想实现这种功能,我是这样做的:
那我需要做什么?我想通过 firebase 进行身份验证,你需要做什么 - 至少我发现 - 实施 APP/LEVEL/STATE 以检查用户是否登录并更新应用程序级别呈现,呈现整个应用程序并相应地强制执行行为。
所以:
function App() {
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setIsLoading(true);
if (user) {
setUser(user);
} else {
setUser(null);
}
setIsLoading(false);
});
return unsubscribe;
}, []);
if (isLoading) return <Spinner />;
return (
<>
<Router>
<Routes>
<Route path='/' element={<PrivateRoute user={user} />}>
<Route index element={<Explore />} />
<Route path='/offers' element={<Offers />} />
<Route path='/profile' element={<Profile />} />
<Route path='/create-listing' element={<CreateListing />} />
<Route path='/category/:categoryName' element={<Category />} />
</Route>
<Route
path='/sign-in'
element={!user ? <SignIn /> : <Navigate to='/' />}
/>
<Route
path='/sign-up'
element={!user ? <SignUp /> : <Navigate to='/' />}
/>
<Route
path='/forgot-password'
element={!user ? <ForgotPassword /> : <Navigate to='/' />}
/>
</Routes>
<Navbar />
</Router>
<ToastContainer autoClose={1000} />
</>
);
}
export default App;
在这里,基本上在组件挂载之后,我们希望useEffect只执行一次并设置auth状态变化的监听器,每当auth状态发生变化,如登录或注销时,onAuthStateChanged的代码块运行,当它每次运行时,它都会设置用户是否有用户,因此会重新呈现 App 本身的组件,并在路由下方相应地工作。如果你像我一样有私有路由,你可以直接将用户作为 prop 传递,然后:
import { Navigate, Outlet } from 'react-router-dom';
function PrivateRoute({ user }) {
return user ? <Outlet /> : <Navigate to='/sign-in' />;
}
export default PrivateRoute;
我想学习firebase路由认证的正确方法,我的意思是:
function App() {
const auth = getAuth();
if (!auth) {
<Spinner />;
}
return (
<>
{auth && (
<Router>
<Routes>
<Route path='/' element={<PrivateRoute />}>
<Route index element={<Explore />} />
<Route path='/offer' element={<Offers />} />
<Route path='/profile' element={<Profile />} />
</Route>
<Route path='/sign-in' element={<SignIn />} />
<Route path='/sign-up' element={<SignUp />} />
<Route path='/forgot-password' element={<ForgotPassword />} />
</Routes>
<Navbar />
</Router>
)}
我有这个代码块,起初我以为我应该得到一个使用 onAuthStateChanged 的 useAuth 钩子,但我意识到来自 getAuth 的这个 auth 变量的工作方式有点相同,所以为什么不使用它而不是钩子呢?
我的 PrivateRoute 看起来像这样:
function PrivateRoute() {
const currentUser = getAuth().currentUser;
return currentUser ? <Outlet /> : <Navigate to='/sign-in' />;
}
问题是一旦应用挂载,由于没有应用级别的状态,它保持不变。
然后,如果我尝试注销并在路由中添加一些逻辑,比如如果用户存在,则不允许路由到注册或登录,它不起作用。
如果我使用 redux 或 context API,我会在登录、注销、注册时分派,但如果没有它们,处理这种路由的正确设置是什么?
一段时间后,我才弄清楚如何做我需要做的事情,所以我post在这里,以防万一有人也遇到这个问题并寻求帮助。
如果你不使用 redux 或 context api 并且仍然想实现这种功能,我是这样做的:
那我需要做什么?我想通过 firebase 进行身份验证,你需要做什么 - 至少我发现 - 实施 APP/LEVEL/STATE 以检查用户是否登录并更新应用程序级别呈现,呈现整个应用程序并相应地强制执行行为。
所以:
function App() {
const [user, setUser] = useState(null);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setIsLoading(true);
if (user) {
setUser(user);
} else {
setUser(null);
}
setIsLoading(false);
});
return unsubscribe;
}, []);
if (isLoading) return <Spinner />;
return (
<>
<Router>
<Routes>
<Route path='/' element={<PrivateRoute user={user} />}>
<Route index element={<Explore />} />
<Route path='/offers' element={<Offers />} />
<Route path='/profile' element={<Profile />} />
<Route path='/create-listing' element={<CreateListing />} />
<Route path='/category/:categoryName' element={<Category />} />
</Route>
<Route
path='/sign-in'
element={!user ? <SignIn /> : <Navigate to='/' />}
/>
<Route
path='/sign-up'
element={!user ? <SignUp /> : <Navigate to='/' />}
/>
<Route
path='/forgot-password'
element={!user ? <ForgotPassword /> : <Navigate to='/' />}
/>
</Routes>
<Navbar />
</Router>
<ToastContainer autoClose={1000} />
</>
);
}
export default App;
在这里,基本上在组件挂载之后,我们希望useEffect只执行一次并设置auth状态变化的监听器,每当auth状态发生变化,如登录或注销时,onAuthStateChanged的代码块运行,当它每次运行时,它都会设置用户是否有用户,因此会重新呈现 App 本身的组件,并在路由下方相应地工作。如果你像我一样有私有路由,你可以直接将用户作为 prop 传递,然后:
import { Navigate, Outlet } from 'react-router-dom';
function PrivateRoute({ user }) {
return user ? <Outlet /> : <Navigate to='/sign-in' />;
}
export default PrivateRoute;