React Router v4 / v5中的嵌套路由

369

我目前在使用React Router v4时遇到了嵌套路由的问题。

最接近的例子是在React-Router v4文档中的路由配置。

我想将我的应用程序分成两个不同的部分:前端和管理区域。

我考虑的大致方案如下:

<Match pattern="/" component={Frontpage}>
  <Match pattern="/home" component={HomePage} />
  <Match pattern="/about" component={AboutPage} />
</Match>
<Match pattern="/admin" component={Backend}>
  <Match pattern="/home" component={Dashboard} />
  <Match pattern="/users" component={UserPage} />
</Match>
<Miss component={NotFoundPage} />
前端页面的布局和样式与管理区域不同。因此,在前端页面中,主页、关于等路由应该是子路由。 应该将/home呈现为Frontpage组件,并在Backend组件中呈现/admin/home。 我尝试了一些其他的变化,但我总是无法访问/home/admin/home

2
感谢您更新问题并提供最终答案!只是一个建议:也许您可以只保留第四个列表和第一个列表,因为其他列表使用的是过时的API版本,会分散注意力。 - Giuliano Vilela
2
哈哈,我不知道这个日期是什么格式:08.05.2017。如果你不想让人们感到困惑,我建议你使用通用的ISO8601日期格式。08是月份还是日期?ISO8601 = 年.月.日 时.分.秒(逐渐更精细) - wesm
1
不错的最终更新解决方案,但我认为您不需要“previousLocation”逻辑。 - tudorpavel
1
完全重写React Router 的动机是什么?最好有一个充分的理由。 - Oliver Watkins
1
这是声明式的方法。因此,您可以像使用React组件一样设置路由。 - datoml
1
请勿在问题中写下答案,而是创建一个答案。不必标记“更新”,因为历史修订已记录。 - Kalle Richter
13个回答

1
我更喜欢使用React函数。这种解决方案简短且更易于阅读
const MainAppRoutes = () => (
    <Switch>
        <Route exact path='/' component={HomePage} />
        {AdminRoute()}                  
        {SampleRoute("/sample_admin")}  
    </Switch>
);

/*first implementation: without params*/
const AdminRoute = () => ([
    <Route path='/admin/home' component={AdminHome} />,
    <Route path='/admin/about' component={AdminAbout} />
]);

/*second implementation: with params*/
const SampleRoute = (main) => ([
    <Route path={`${main}`} component={MainPage} />,
    <Route path={`${main}/:id`} component={MainPage} />
]); 

1

这段代码在v6版本下适用

index.js

ReactDOM.render(
  <React.StrictMode>
    <BrowserRouter>
      <Routes>
        <Route path="/" element={<App />}>
          <Route path="login" element={<Login />} />
          <Route path="home" element={<Home />} />
        </Route>
      </Routes>
    </BrowserRouter>
  </React.StrictMode>,
  document.getElementById('root')
);

App.js:

function App(props) {
  useEffect(() => {
    console.log('reloaded');
// Checking, if Parent component re-rendering or not *it should not be, in the sense of performance*, this code doesn't re-render parent component while loading children
  });
  return (
    <div className="App">
      <Link to="login">Login</Link>
      <Link to="home">Home</Link>
      <Outlet /> // This line is important, otherwise we will be shown with empty component
    </div>
  );
}

login.js:

const Login = () => {
    return (
        <div>
            Login Component
        </div>
    )
};

home.js:

const Home= () => {
    return (
        <div>
            Home Component
        </div>
    )
};

-6
interface IDefaultLayoutProps {
    children: React.ReactNode
}

const DefaultLayout: React.SFC<IDefaultLayoutProps> = ({children}) => {
    return (
        <div className="DefaultLayout">
            {children}
        </div>
    );
}


const LayoutRoute: React.SFC<IDefaultLayoutRouteProps & RouteProps> = ({component: Component, layout: Layout, ...rest}) => {
const handleRender = (matchProps: RouteComponentProps<{}, StaticContext>) => (
        <Layout>
            <Component {...matchProps} />
        </Layout>
    );

    return (
        <Route {...rest} render={handleRender}/>
    );
}

const ScreenRouter = () => (
    <BrowserRouter>
        <div>
            <Link to="/">Home</Link>
            <Link to="/counter">Counter</Link>
            <Switch>
                <LayoutRoute path="/" exact={true} layout={DefaultLayout} component={HomeScreen} />
                <LayoutRoute path="/counter" layout={DashboardLayout} component={CounterScreen} />
            </Switch>
        </div>
    </BrowserRouter>
);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接