我是React的新手。我在App.js中对路由器配置做出了这样的反应:
<BrowserRouter>
<div className="App">
<Header />
<Switch>
<Route exact path="/" component={Home}>
</Route>
<Route exact path="/management" component={Management}>
</Route>
<Route exact path="/sign-up" component={SignUpForm}>
</Route>
<Route exact path="/sign-in" component={SignInForm}>
</Route>
<Route component={Error}>
</Route>
</Switch>
</div>
</BrowserRouter >
我希望页眉显示在每个页面中,页眉有一个注销按钮,单击后我想重定向到/ sign-in页面。在我的标头组件中,就像这样:
class Header extends Component {
constructor(props) {
super(props);
this.state = {
redirect: false
}
}
logout = () => {
sessionStorage.setItem("userToken", '');
sessionStorage.clear();
this.setState({ redirect: true });
}
render() {
if (this.state.redirect) {
return (
<Redirect to={'/sign-in'} />
)
}
return (
<div>
<Navbar collapseOnSelect expand="md" bg="dark" variant="dark" fixed="top" >
......
<NavLink to="/management" className="header-link"><FontAwesomeIcon icon="cog" size="lg" /></NavLink>
<button type='button' onClick={this.logout}>Log Out</button>
</Nav>
</Navbar.Collapse>
</Navbar>
</div>
);
}
}
export default Header;
会出现错误“警告:您试图重定向到当前正在使用的同一路线:“ /登录”,并且导航栏仅会消失在登录正文中。请问我知道什么是正确的方法吗?我也尝试过this.props.history.push('/ sign-in')但没有props.history,可能是因为标头不在路由中吗?我应该和Router一起使用吗?还是应该其实只是让每个页面导入标头都放到app.js中?或者实际上是正确的方法是什么?非常感谢您的帮助!
答案 0 :(得分:2)
与Routes绑定的组件可以作为道具访问历史对象,因此您可以根据需要对其进行更改,例如注销。由于您的Header组件无权访问历史记录对象,因此您将不得不使用较低级别的路由器来授予其对历史记录对象的访问权限:
import { Router } from "react-router"
import { createBrowserHistory } from "history"
const history = createBrowserHistory()
<Router history={history}>
<div className="App">
<Header history={history} />
<Switch>
<Route exact path="/" component={Home}>
</Route>
<Route exact path="/management" component={Management}>
</Route>
<Route exact path="/sign-up" component={SignUpForm}>
</Route>
<Route exact path="/sign-in" component={SignInForm}>
</Route>
<Route component={Error}>
</Route>
</Switch>
</div>
</Router>
您现在可以在标头组件中调用history.push('/login')
请参阅参考资料:https://reacttraining.com/react-router/web/api/Router/history-object
答案 1 :(得分:2)
您可以使用HOC通过路由实现登录/注销,HOC会在每次路由更改时检查会话项。如果会话具有userToken
,则它将重定向到给定的组件,否则将重定向到登录组件。
import React from "react"
import {Redirect} from "react-router-dom"
export const PrivateRoute = ({component: Component, ...rest}) => (
<Route {...rest} render={(props) => (
sessionStorage.getItem('userToken') ? <Component {...props} /> : <Redirect to="/sign-in"/>
)} />
)
导入<PrivateRoute>
并将其用作授权路径。并将所有其他路径保留为不需要授权的普通路径。
<BrowserRouter>
<div className="App">
<Header />
<Switch>
<PrivateRoute path="/" component={Home} />
<PrivateRoute path="/management" component={Management} />
<Route path="/sign-up" component={SignUpForm} />
<Route path="/sign-in" component={SignInForm} />
<Route component={Error} />
</Switch>
</div>
</BrowserRouter >
因此,当您注销时,会话项将被删除并自动重定向到登录页面。
class Header extends Component {
....
logout = () => {
sessionStorage.removeItem("userToken");
sessionStorage.clear();
}
render() {
return (
<div>
...
<button type='button' onClick={this.logout}>Log Out</button>
</div>
)
}
}
export default Header;
答案 2 :(得分:1)
您在这里提到两种方法。您可以使用高阶组件'withRouter',该组件使组件可以访问历史记录对象。通过使用将history对象作为道具传递给组件的方法,您可以推入所需的路线。
个人而言,我喜欢设置退出链接以呈现一个组件,该组件包含注销逻辑,并在完成后呈现重定向到登录的内容。这样,用户可以根据需要直接转到退出链接,您可以根据需要从应用程序中的任何位置链接到退出链接,而不必重复逻辑。
在您的浏览器路由器中,您可以为“ / logout”添加一个路径,以呈现这样的组件(根据您的逻辑):
import React, { Component } from 'react';
import { Redirect } from 'react-router';
export default class LogOut extends Component {
state = {
redirect: false,
};
componentDidMount() {
sessionStorage.setItem("userToken", '');
sessionStorage.clear();
this.setState({ redirect: true });
}
render() {
return this.state.redirect ?
<Redirect to={'/sign-in'} /> :
null;
}
}
通常,我会先发出ajax请求以清除会话,然后在完成后立即设置setState,但您的请求全在服务器端。