我可以在我的 React-Django 应用程序中注册、登录和注销用户。我在登录时在本地存储中设置用户数据(用户名、电子邮件等)。但是,当我尝试转到受保护的路由(例如“/about”)时,我被重定向到“/login”,因为 React 在尝试访问受保护的路由时似乎无法足够快地检查用户状态路线。当我访问受保护的路由时,我正在控制台记录用户状态,只是为了证明该状态仍然存在,但检索速度不够快(在渲染之前)。
当我登录然后转到受保护的“/about”路由时,我的 console.logs 是:
AuthContext state: {user: null}
AuthContext state: {user: null}
AuthContext state: {user: {…}}
AuthContext state: {user: {…}}
所以,在受保护的页面呈现之前,我需要帮助以足够快的速度访问用户状态。想法?
这是我的代码:
src/context/AuthContext.js:
export const AuthContext = createContext()
export const authReducer = (state, action) => {
switch (action.type){
case "LOGIN":
return { user: action.payload }
case "LOGOUT":
localStorage.removeItem("mysUser")
return { user: null }
default:
return state
}
}
export const AuthContextProvider = ({ children }) =>{
const [state, dispatch] = useReducer(authReducer, {
user: null
})
useEffect(() => {
const user = JSON.parse(localStorage.getItem("mysUser"))
if (user){
dispatch({ type: "LOGIN", payload: user })
}
}, [])
console.log("AuthContext state: ", state)
return (
<AuthContext.Provider value={{ ...state, dispatch}}>
{ children }
</AuthContext.Provider>
)
}
src/App.js
function App() {
// auth state
const { user } = useAuthContext()
return (
<div className="App">
<BrowserRouter>
<NavbarComponent/>
<div>
<Routes>
{/* protected route */}
<Route
path="/about"
element={user ? <About /> : <Navigate to="/login" />}
exact
/>
{/* non-protected routes */}
<Route path="/" element={<Home />} />
<Route path="/signup" element={<Signup />} exact />
<Route path="/login" element={<Login/>} exact />
</Routes>
</div>
<FooterComponent />
</BrowserRouter>
</div>
);
}
export default App;
在你的
App
函数中你可以这样做
是的,useEffect 确实在渲染后运行,但如果您这样做,链接将在用户可用时更新。
因为您的自定义钩子已经在渲染发生之后而不是之前触发。您可以使用 useEffect 观察变化并与用户一起更新状态值,这将导致重新渲染,但您不会注意到重新渲染,因为您只是在幕后交换组件。
import {useState, useEffect} from 'react'; //added
function App() {
const [currUser, setCurrUser] = useState(null) //added
// auth state
const { user } = useAuthContext()
useEffect(() => { //added
if(user) {
setCurrUser(user);
}
}, [user])
return (
<div className="App">
<BrowserRouter>
<NavbarComponent/>
<div>
<Routes>
{/* protected route */}
{/* changed user to currUser */}
<Route
path="/about"
element={currUser ? <About /> : <Navigate to="/login" />}
exact
/>
{/* non-protected routes */}
<Route path="/" element={<Home />} />
<Route path="/signup" element={<Signup />} exact />
<Route path="/login" element={<Login/>} exact />
</Routes>
</div>
<FooterComponent />
</BrowserRouter>
</div>
);
}
export default App;