React Router SPA登录页独立布局路由配置求助
嘿,我帮你梳理下问题所在,然后一步步解决它~
你的核心问题出在嵌套了多个Router以及路由结构的逻辑顺序上,React Router只需要一个顶层的Router就够了,嵌套多个会导致路由上下文混乱,让Login页面意外继承了主布局。下面是具体的修改方案:
第一步:清理嵌套的Router
首先把Main.js里的<HashRouter>删掉!因为App.js已经用了<BrowserRouter>作为顶层路由容器,嵌套多个Router会让路由跳转逻辑冲突,这是新手常踩的坑。
第二步:调整App.js的路由结构
我们要把Login页面设为独立路由,优先匹配;剩下的所有页面都交给带主布局的Main组件处理,修改后的App.js如下:
import React, { Component } from 'react'; import Main from "./Main"; import Login from "./components/Login"; import { Route, Switch, BrowserRouter } from "react-router-dom"; class App extends Component { render() { return ( <BrowserRouter> <Switch> {/* 独立登录页,不加载主布局 */} <Route path="/login" component={Login} /> {/* 所有其他路径都使用主布局,Main内部处理子路由 */} <Route path="/" component={Main} /> </Switch> </BrowserRouter> ); } } export default App;
这里把/login路由放在前面,因为Switch会匹配第一个符合条件的路由,确保访问登录页时直接渲染Login组件,不会进入Main的布局。
第三步:修改Main.js的子路由逻辑
去掉HashRouter后,给内部子路由加上<Switch>,确保每次只渲染一个页面组件,同时完善导入逻辑:
import React, { Component } from 'react'; import Navigation from './components/Navigation' import LeftSidebar from './components/LeftSidebar'; import RightSidebar from './components/RightSidebar'; import { fakeAuth } from "./components/Login"; import { Route, Switch, Redirect, withRouter } from "react-router-dom"; /* Home component */ const Home = () => ( <div> <h2>Home</h2> </div> ) /* Category component */ const Category = () => ( <div> <h2>Category</h2> </div> ) /* Products component */ const Products = () => ( <div> <h2>Products</h2> </div> ) class Main extends Component { render() { return ( <div className="container container-fluid"> <Navigation/> <div className="row"> <div className="col-md-3"> <LeftSidebar/> </div> <div className="col-md-6"> {/* 用Switch确保只匹配一个子路由 */} <Switch> <Route exact path="/" component={Home} /> <Route path="/category" component={Category}/> <PrivateRoute authed={fakeAuth.isAuthenticated} path='/products' component={Products} /> </Switch> </div> <div className="col-md-3"> <RightSidebar/> </div> </div> </div> ); } } const PrivateRoute = ({ component: Component, ...rest }) => { return ( <Route {...rest} render={props => fakeAuth.isAuthenticated === true ? ( <Component {...props} /> ) : ( <Redirect to={{ pathname: "/login", state: { from: props.location } }} /> )} /> ); }; const AuthButton = withRouter( ({ history }) => fakeAuth.isAuthenticated ? ( <p> Welcome!{" "} <button onClick={() => { fakeAuth.signout(() => history.push("/")); }}> Sign out </button> </p> ) : ( <p>You are not logged in.</p> ) ); export default Main;
第四步:完善Login.js的退出功能
原来的fakeAuth里缺少signout方法,点击退出按钮会报错,补上这个方法:
import React from 'react'; import { Redirect } from "react-router-dom"; class Login extends React.Component { constructor() { super(); this.state = { redirectToReferrer: false } this.login = this.login.bind(this); } login() { fakeAuth.authenticate(() => { this.setState({ redirectToReferrer: true }) }) } render() { const { from } = this.props.location.state || { from: { pathname: '/' } } const { redirectToReferrer } = this.state; if (redirectToReferrer) { return ( <Redirect to={from} /> ) } return ( <div> <p>You must log in to view the page at {from.pathname}</p> <button onClick={this.login}>Log in</button> </div> ) } } /* A fake authentication function */ export const fakeAuth = { isAuthenticated: false, authenticate(cb) { this.isAuthenticated = true; setTimeout(cb, 100); }, // 添加退出方法 signout(cb) { this.isAuthenticated = false; setTimeout(cb, 100); } }; export default Login
现在你再运行项目,点击Home、Category、Products时,页面会加载在主布局里;访问/login时,会显示独立的登录页面,完全符合你的需求啦~
内容的提问来源于stack exchange,提问作者Alice
相关产品推荐
相关产品推荐

