这是我的路由器:
const Router = () => {
const { user } = useContext(UserContext)
return (
<Switch>
{user.token ?
<>
<Route exact path="/" component={Wall}/>
<Route path="/profile" component={Profile}/>
<Route path="/discover" component={Discover}/>
<Route path="/settings" component={Settings}/>
<Route path="/post" component={Post}/>
<Route path="/deleteuser" component={DeleteUser}/>
<Route path="/profileimg" component={ProfileImg}/>
</> :
<>
<Route exact path="/" component={Splash}/>
<Route path="/auth" component={Auth}/>
<Route path="/create" component={Create}/>
<Route path="/forgot" component={Forgot}/>
</>
}
{!user.token && <Redirect to="/"/>}
<Route component={Notfound}/>
</Switch>
)
}
如您所见,我根据用户在上下文中是否有令牌来保护路由。
在我的应用程序中,我有一个函数logout()
,可以清除本地存储和状态信息,其中当然包括用户令牌。
我的问题是,如果用户在受保护的路由上并且调用了此logout()
函数,我似乎找不到有关重定向到"/"
的最佳方式的任何文档。
要清楚的是,我想要的是:logout()
=><Redirect to="/"/>
因为状态中不再有令牌。
我已经想到了多种方法,但我正在寻找最佳或最干净的解决方案:
一种使用历史记录的方法 -
history.location.pathname === "/protected" && !user.token && <Redirect to="/"/>
我确定有一种方法可以通过路由器中的<Redirect/>
实现相同的逻辑?一种在每个受保护组件的 JSX 中使用重定向的方法 -
{!user.token && <Redirect to="/"/>}
我宁愿不把它放在我拥有的每个受保护路由的组件 JSX 中!我可以将历史道具传递给
logout()
函数并执行此操作 -history && history.push("/")
我也宁愿不这样做,因为每次调用logout()
时都需要传递历史道具,这感觉相当混乱。
您可以有一个路由<Route exact path="/logout" component={Logout}/>
。
跟
export default const Logout = () => {
useEffect(() => {
//remove token here
}, []);
return <Redirect to="/">
}
或功能注销,并过渡到您的家,例如
const history = useHistory();
const logout = () => {
// remove tokens
history.push('/');
}
或两者兼而有之
const logout = () => {
// remove tokens
return <Redirect to="/"/>
}
我在路由器内什么都没做.js或者最后logout()
。相反,我使用了一种在撰写本文时显然已经逃脱了我脑海的方法。
为了使用 React 重定向,我们需要一种方法来触发重新渲染。我不确定上面讨论的所有方法是否实际上都重新渲染,但是在 React 中实现此目的的默认方法是更新上下文或您的存储状态(如果您使用的是 Redux(。然后,根据该状态,在已知将始终呈现的组件中,添加一些代码进行重定向。
这是我Nav
的代码:
const Nav = ({ history }) => {
const { user, setUser } = useContext(UserContext)
useEffect(() => { // Redirect if user.redirect === truthy.
user.redirect && history.push(user.redirect)
setUser({ ...user, redirect: false })
}, [user.redirect]) // eslint-disable-line react-hooks/exhaustive-deps
*** rest of the code in Nav ***
}