Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
937 views
in Technique[技术] by (71.8m points)

reactjs - React Router v5.0 Nested Routes

I'm building a react app and I can't make the routing work.

  1. I need one common layout (header, footer) for a few Auth routes (/login, sign-up, forgot-password, etc...)

  2. And I need need another common layout for the rest of the protected parts of the app (Home, Dashboard, etc...)

  3. I need another 404 page without any layout.

I've tried several techniques from those links:

But could reach working version.

This is what I'm currently have:

(Note: for now I'm ignoring the need to block non logged-in users into the private routes of AppLayout, I'll handle that right after)

const App: React.FC = () => {
    const history = createBrowserHistory();

    return (
        <div className="App">
            <Router history={history}>
                <Switch>
                    <AppLayout>
                        <Route path="/home" component={HomePage}/>
                        <Route path="/dashboard" component={DashboardPage}/>
                        ...
                    </AppLayout>
                    <AuthLayout>
                        <Route path="/login" component={LoginPage}/>
                        <Route path="/sign-up" component={SignUpPage}/>
                        ...
                    </AuthLayout>
                    <Route path="*" component={NotFoundPage} />
                </Switch>
            </Router>
        </div>
    );
};

export default App;

Both AuthLayout and AppLayout are simple and similar to that (just with different header/footer for each):

class AppLayout extends Component {
    render() {
        return (
            <div className="AppLayout">
                <header>...</header>
                {this.props.children}
                <footer>...</footer>
            </div>
        );
    }
}

export default AppLayout;

The problem is that only routes from the AppLayout are rendered. Other routes just showing the AppLayout header and footer without any content.

Those are the react versions I'm using:

    "react": "^16.8.6",
    "react-dom": "^16.8.6",
    "react-router-dom": "^5.0.0",

Any help would be appreciated.

Thanks in advance.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Each of your layout should have a path component to differentiate from other layouts.

For example

Auth layouts could reside under /auth eg, login would /auth/login, signup would be /auth/signup

App layout could go under /app eg, dashboard would be /app/dashboard, home would be /app/home

Working Demo

Edit hungry-dubinsky-q1l62

App.js

import { Switch, BrowserRouter, Route, Redirect } from "react-router-dom";

function App() {
  return (
    <BrowserRouter>
      <Layouts />
    </BrowserRouter>
  );
}

Layouts.js

const NotFound = () => <h1>Not Found</h1>;

function Layouts() {
  return (
    <Switch>
      <Route path="/auth" component={AuthLayout} />
      <Route path="/app" component={AppLayout} />
      <Route path="/" component={NotFound} />
    </Switch>
  );
}

AuthLayout

const Signup = () => <p>Login</p>;
const Login = () => <p>Sign up</p>;

function AuthLayout() {
  return (
    <div>
      <h1>Auth Layout</h1>
      <Route path="/auth/signup" exact component={Signup} />
      <Route path="/auth/login" exact component={Login} />
      <Redirect from="/auth" to="/auth/login" exact />
    </div>
  );
}

AppLayout

const Home = () => <p>Home</p>;
const Dashboard = () => <p>Dashboard</p>;

function AppLayout() {
  return (
    <div>
      <h1>App Layout</h1>
      <Route path="/app/home" exact component={Home} />
      <Route path="/app/dashboard" exact component={Dashboard} />
      <Redirect from="/app" to="/app/home" exact />
    </div>
  );
}

Also if you want to protect certain routes from being rendered if not authenticated, then you can create a PrivateRoute component that would redirect to auth layout if not authenticated.

PrivateRoute.js

const PrivateRoute = ({ component: Component, ...rest }) => (
  <Route
    {...rest}
    render={props => sessionStorage.token // your auth mechanism goes here
      ? <Component {...props} />
      : <Redirect to={{ pathname: '/auth' }} />}
  />
);

You can use this PrivateRoute component instead of react-router's Route component.

Eg:

<PrivateRoute path="/app" component={AppLayout} />


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...