尝试进行某些路由需要身份验证。
我有这个:
class App extends Component { render() { const menuClass = `${this.props.contentMenuClass} col-xs-12 col-md-9`; return ( <BrowserRouter history={browserHistory}> <div className="App"> <Header properties={this.props} /> <div className="container-fluid"> <div className="row"> <SideNav /> <div className={menuClass} id="mainContent"> <Switch> {routes.map(prop => ( <Route path={prop.path} component={prop.component} key={prop.id} render={() => ( !AuthenticationService.IsAutheenticated() ? <Redirect to="/Login"/> : <Route path={prop.path} component={prop.component} key={prop.id}/> )} /> ))} </Switch> </div> </div> </div> {/* <Footer /> */} </div> </BrowserRouter> ); } } const mapStateToProps = state => ({ contentMenuClass: state.menu, }); export default connect(mapStateToProps)(App);
注意:是的,身份验证服务可以正常工作。
对于每条路由,我都会检查用户是否已通过身份验证,如果没有通过身份验证,则要将他们重定向到登录页面,如果已通过身份验证,则它将以“ /”路由登陆到第一页。
我得到的是:
> react-dom.development.js:14227 The above error occurred in the <Route> > component: > in Route (created by App) > in Switch (created by App) > in div (created by App) > in div (created by App) > in div (created by App) > in div (created by App) > in Router (created by BrowserRouter) > in BrowserRouter (created by App) > in App (created by Connect(App)) > in Connect(App) > in Provider
我在哪里做错了?
一个简单的解决方案是制作一个HOC包含所有受保护路线的(高阶组件)。
HOC
根据您的应用程序的嵌套方式,您可能需要利用本地redux状态。
redux
工作示例:https : //codesandbox.io/s/5m2690nn6n(使用本地状态)
路线/index.js
import React from "react"; import { BrowserRouter, Switch, Route } from "react-router-dom"; import Home from "../components/Home"; import Players from "../components/Players"; import Schedule from "../components/Schedule"; import RequireAuth from "../components/RequireAuth"; export default () => ( <BrowserRouter> <RequireAuth> <Switch> <Route exact path="/" component={Home} /> <Route exact path="/players" component={Players} /> <Route path="/schedule" component={Schedule} /> </Switch> </RequireAuth> </BrowserRouter> );
组件/RequireAuth.js
import React, { Component, Fragment } from "react"; import { withRouter } from "react-router-dom"; import Login from "./Login"; import Header from "./Header"; class RequireAuth extends Component { state = { isAuthenticated: false }; componentDidMount = () => { if (!this.state.isAuthenticated) { this.props.history.push("/"); } }; componentDidUpdate = (prevProps, prevState) => { if ( this.props.location.pathname !== prevProps.location.pathname && !this.state.isAuthenticated ) { this.props.history.push("/"); } }; isAuthed = () => this.setState({ isAuthenticated: true }); unAuth = () => this.setState({ isAuthenticated: false }); render = () => !this.state.isAuthenticated ? ( <Login isAuthed={this.isAuthed} /> ) : ( <Fragment> <Header unAuth={this.unAuth} /> {this.props.children} </Fragment> ); } export default withRouter(RequireAuth);
或者,您可以创建一个包含受保护路由的受保护组件,而不是包装路由。
工作示例:https : //codesandbox.io/s/yqo75n896x(使用redux代替本地状态)。
import React from "react"; import { BrowserRouter, Route, Switch } from "react-router-dom"; import { createStore } from "redux"; import { Provider } from "react-redux"; import Home from "../components/Home"; import Header from "../containers/Header"; import Info from "../components/Info"; import Sponsors from "../components/Sponsors"; import Signin from "../containers/Signin"; import RequireAuth from "../containers/RequireAuth"; import rootReducer from "../reducers"; const store = createStore(rootReducer); export default () => ( <Provider store={store}> <BrowserRouter> <div> <Header /> <Switch> <Route exact path="/" component={Home} /> <Route path="/info" component={Info} /> <Route path="/sponsors" component={Sponsors} /> <Route path="/protected" component={RequireAuth} /> <Route path="/signin" component={Signin} /> </Switch> </div> </BrowserRouter> </Provider> );
容器/RequireAuth.js
import React from "react"; import { Route, Redirect } from "react-router-dom"; import { connect } from "react-redux"; import ShowPlayerRoster from "../components/ShowPlayerRoster"; import ShowPlayerStats from "../components/ShowPlayerStats"; import Schedule from "../components/Schedule"; const RequireAuth = ({ match: { path }, isAuthenticated }) => !isAuthenticated ? ( <Redirect to="/signin" /> ) : ( <div> <Route exact path={`${path}/roster`} component={ShowPlayerRoster} /> <Route path={`${path}/roster/:id`} component={ShowPlayerStats} /> <Route path={`${path}/schedule`} component={Schedule} /> </div> ); export default connect(state => ({ isAuthenticated: state.auth.isAuthenticated }))(RequireAuth);
您甚至可以通过创建包装函数来获得更多的模块化。您只需包装组件即可选择任何路线。
例如: <Route path="/blog" component={RequireAuth(Blog)} />
<Route path="/blog" component={RequireAuth(Blog)} />