Jos*_*ker 7 reactjs react-router-dom react-hooks
我在 React 中有一个简单的身份验证应用程序,问题是当用户登录时,他被重定向到他的个人资料,但我的导航栏组件未正确呈现。仅在刷新页面后应用更改,但在请求直接重定向时不应用更改。
应用程序组件:
function App() {
const auth = useAuth();
return (
<>
<Router>
{auth.auth ? <Navbar/> : <NotAuthNavbar/>}
<Routes>
<Route path="/" element={<Dashboard/>}/>
<Route path="/login" element={<Login/>}/>
<Route path="/signup" element={<Register/>}/>
<Route path="/profile"
element={
<PrivateRoute>
<Profile/>
</PrivateRoute>
}
/>
<Route path="/confirm-register/:tokenConfirm" element={<ConfirmRegister/>}/>
<Route path="/registered" element={<RegisterMessage/>}/>
</Routes>
</Router>
</>
);
}
export default App;
Run Code Online (Sandbox Code Playgroud)
验证自定义挂钩:
const useAuth = () => {
const [auth,setAuth] = useState(null);
const [user,setUser] = useState({});
const isAuth = async() => {
await axios.get('http://localhost:5000/api/logged-user/',{withCredentials:true})
.then(res => {
setUser(res.data);
setAuth(true);
})
.catch(error => {
setAuth(false);
});
}
useEffect(() => {
isAuth();
},[auth])
return{
auth:auth,
user:user
}
}
export default useAuth;
Run Code Online (Sandbox Code Playgroud)
导航栏和 NotAuthNavbar:
///Navbar.jsx
const Navbar = () => {
const auth = useAuth();
const navigate = useNavigate();
const logout = async() =>{
await axios.get("http://localhost:5000/api/logout/",{withCredentials:true})
.then(res => {
console.log(res.data);
navigate('/login');
return;
})
}
return(
<section>
<div className="navbar">
<ul className="navbar-menu">
<li><Link to={"/dashboard"}>Dashboard</Link></li>
<li><Link to={"/profile"}>Welcome {auth.user.username}</Link></li>
<li><button type='button' onClick={logout}>Logout</button></li>
</ul>
</div>
<Outlet />
</section>
)
}
export default Navbar;
/// NotAuthNavbar.jsx
const NotAuthNavbar = () => {
return(
<section>
<div className="navbar">
<ul className="navbar-menu">
<li><Link to={"/dashboard"}>Dashboard</Link></li>
<li><Link to={"/signup"}>Sign Up</Link></li>
<li><Link to={"/login"}>Sign In</Link></li>
</ul>
</div>
<Outlet />
</section>
)
}
export default NotAuthNavbar;
Run Code Online (Sandbox Code Playgroud)
当用户登录时,我通过 React-router-dom 重定向到他的个人资料。
我不知道如何在登录和注销后更新导航栏。我忍不住想有一些我没有看到的小细节,但我已经被困在这个问题上几个小时了。
提前致谢。
编辑
这是登录的功能
const login = async(e) => {
e.preventDefault();
await axios.post("http://localhost:5000/api/signin/",{
email:email.email,
password:password.password
},{
withCredentials:true,
})
.then(res => {
setIsSubmitted(true);
if(res.status === 200){
alert('!LOGGED');
navigate('/profile');
return res.data;
}
})
.catch(error => {
let parsedErrors = [];
parsedErrors = JSON.parse(error.request.response);
setHandleErrors(parsedErrors);
setIsSubmitted(true);
})
}
Run Code Online (Sandbox Code Playgroud)
Dre*_*ese 11
React hooks 不共享状态。
将useAuth状态移动到 React 上下文中并将其提供给应用程序。然后,该useAuth钩子应该使用该useContext钩子来访问单一身份验证状态。
例子:
创建一个AuthContext、provider 和 hook。
import { createContext, useContext, useEffect, useState } from 'react';
const AuthContext = createContext({
auth: null,
setAuth: () => {},
user: null,
});
export const useAuth = () => useContext(AuthContext);
const AuthProvider = ({ children }) => {
const [auth, setAuth] = useState(null);
const [user, setUser] = useState(null);
useEffect(() => {
const isAuth = async () => {
try {
const res = await axios.get(
'http://localhost:5000/api/logged-user/',
{ withCredentials: true }
);
setUser(res.data);
} catch(error) {
setUser(null);
};
};
isAuth();
}, [auth]);
return (
<AuthContext.Provider value={{ auth, setAuth, user }}>
{children}
</AuthContext.Provider>
);
};
export default AuthProvider;
Run Code Online (Sandbox Code Playgroud)
用App元件包裹元件AuthProvider。
import AuthProvider from "../path/to/AuthContext";
...
<AuthProvider>
<App />
</AuthProvider>
Run Code Online (Sandbox Code Playgroud)
现在有了一个单一的状态auth,所有钩子都引用相同的状态。useruseAuth
function App() {
const { auth } = useAuth();
return (
<Router>
{auth ? <Navbar /> : <NotAuthNavbar />}
<Routes>
<Route path="/" element={<Dashboard />} />
<Route path="/login" element={<Login />} />
<Route path="/signup" element={<Register />} />
<Route
path="/profile"
element={(
<PrivateRoute>
<Profile />
</PrivateRoute>
)}
/>
<Route path="/confirm-register/:tokenConfirm" element={<ConfirmRegister />} />
<Route path="/registered" element={<RegisterMessage />} />
</Routes>
</Router>
);
}
Run Code Online (Sandbox Code Playgroud)
成功注销后,访问setAuth更新程序功能以设置false。auth
const Navbar = () => {
const { setAuth, user } = useAuth();
const navigate = useNavigate();
const logout = async () => {
const res await axios.get(
"http://localhost:5000/api/logout/",
{ withCredentials: true }
);
console.log(res.data);
setAuth(false);
navigate('/login');
}
return(
<section>
<div className="navbar">
<ul className="navbar-menu">
<li><Link to={"/dashboard"}>Dashboard</Link></li>
<li><Link to={"/profile"}>Welcome {user.username}</Link></li>
<li><button type='button' onClick={logout}>Logout</button></li>
</ul>
</div>
<Outlet />
</section>
);
};
Run Code Online (Sandbox Code Playgroud)
login功能使用useAuth钩子访问setAuth更新程序函数并auth在身份验证成功后设置 true。
const { setAuth } = useAuth();
...
const login = async (e) => {
e.preventDefault();
try {
const res = await axios.post(
"http://localhost:5000/api/signin/",
{
email: email.email,
password: password.password
},
{
withCredentials: true,
}
);
if (res.status === 200) {
alert('!LOGGED');
setAuth(true);
navigate('/profile');
}
} catch(error) {
setHandleErrors(JSON.parse(error.request.response));
} finally {
setIsSubmitted(true);
}
}
Run Code Online (Sandbox Code Playgroud)
注意:与 Promise 链混合是反模式async/await。一般来说,您应该选择其中之一。我已经使用async/awaitwithtry/catch来处理被拒绝的承诺和可能发生的其他错误。
| 归档时间: |
|
| 查看次数: |
12145 次 |
| 最近记录: |