React Router v5.0 Вложенные маршруты - PullRequest
0 голосов
/ 22 июня 2019

Я создаю приложение реагирования и не могу заставить работать маршрутизацию.

  1. Мне нужен один общий макет (верхний и нижний колонтитулы) для нескольких маршрутов аутентификации (* 1005)*, sign-up, forgot-password и т. Д.)

  2. И мне нужна еще одна общая раскладка для остальных защищенных частей приложения (Home, Dashboard и т. Д.)

  3. Мне нужна еще 404 страница без какого-либо макета.

Я пробовал несколько техник по этим ссылкам:

Но может дойти до рабочей версии.

Это то, что у меня сейчас есть:

(Примечание: длятеперь я игнорирую необходимость блокировать не вошедших в систему пользователей в частные маршруты AppLayout, я справлюсь с этим сразу после этого)

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;

Оба AuthLayout и AppLayout просты и похожик этому (только с различным заголовком / нижним колонтитулом для каждого):

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

export default AppLayout;

Проблема в том, что отображаются только маршруты из AppLayout.Другие маршруты просто показывают AppLayout header и footer без какого-либо контента.

Вот те версии реакции, которые я использую:

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

Любая помощь будет принята.

Заранее спасибо.

Ответы [ 3 ]

0 голосов
/ 22 июня 2019

Каждый ваш макет должен иметь компонент пути, чтобы отличаться от других макетов.

Например

Схемы аутентификации могут находиться в /auth, например, логин будет /auth/login, регистрация будет /auth/signup

Макет приложения может быть меньше /app, например, приборная панель будет /app/dashboard, дом будет /app/home

Рабочая демоверсия

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>
  );
}

Также, если вы хотите защитить определенные маршруты от рендеринга, если они не аутентифицированы, вы можете создать PrivateRoute компонент, который будет перенаправлять на макет аутентификации, если не аутентифицирован.

PrivateRoute.js

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

Вы можете использовать этот PrivateRoute компонент вместо react-router Route компонента.

Например:

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

0 голосов
/ 29 июня 2019

Оба решения @Gaurab Kc и @johnny peter великолепны, хотя в итоге я сделал что-то подобное:

<Router history={history}>
    <Switch>
        <PrivateRoute
            path="/home"
            component={HomePage}>
        </PrivateRoute>
        <PrivateRoute
            path="/dashboard"
            component={DashboardPage}>
        </PrivateRoute>
        <AuthRoute
            path="/login"
            component={LoginPage}>
        </AuthRoute>
        <AuthRoute
            path="/sign-up"
            component={SignUpPage}>
        </AuthRoute>
        <Route path="*" component={NotFoundPage}/>
    </Switch>
</Router>

AuthRoute & PrivateRoute примерно такие:

interface PrivateRouteProps extends RouteProps {
    component: any;
}

const PrivateRoute = (props: PrivateRouteProps) => {
    const {component: Component, ...rest} = props;

    return (
        <Route
            {...rest}
            render={(routeProps) =>
                localStorage.getItem('user') ? (
                    <div>
                       ... // here is the app header
                       <Component {...routeProps} />
                       .. // here is the app footer
                    </div>
                ) : (
                    <Redirect
                        to={{
                            pathname: '/login',
                            state: {from: routeProps.location}
                        }}
                    />
                )
            }
        />
    );
};

export default PrivateRoute;
interface AuthRouteProps extends RouteProps {
    component: any;
}

const AuthRoute = (props: AuthRouteProps) => {
    const {component: Component, ...rest} = props;

    return (
        <Route
            {...rest}
            render={(routeProps) =>
                (
                    <div>
                       ... // here is the auth header
                       <Component {...routeProps} />
                       .. // here is the auth footer
                    </div>
                )
            }
        />
    );
};

export default AuthRoute;
0 голосов
/ 22 июня 2019

Вы можете попробовать использовать два разных оператора switch для обработки ваших Auth и Protected маршрутов. У меня был похожий вариант использования на работе, и для меня было подходящим использование двух комплектов блоков переключателей, при котором только один работал одновременно.

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

    return (
        <div className="App">
            <Router history={history}>
                {isLoggedIn ? <PrivateRoutes /> : <AuthRoutes />}
            </Router>
        </div>
    );
};


const PrivateRoutes: React.FC = () => {
    return (
        <>
            <Header />
            <Switch>
                <Route path="/home" component={HomePage} />
                <Route path="/dashboard" component={DashboardPage} />
                <Route path="*" component={NotFoundPage} />
            </Switch>
            <Footer />
        </>
    );
};

const AuthRoutes: React.FC = () => {
    return (
        <>
            <Header />
            <Switch>
                <Route path="/login" component={LoginPage} />
                <Route path="/sign-up" component={SignUpPage} />
                <Route path="*" component={NotFoundPage} />
            </Switch>
            <Footer />
        </>
    );
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...