Reactjs 使用布局页面或每页多个组件的React路由器
我正在将react router添加到现有项目中 目前,一个模型被传递到一个根组件,该根组件包含一个用于子导航的导航组件和一个主组件Reactjs 使用布局页面或每页多个组件的React路由器,reactjs,react-router,Reactjs,React Router,我正在将react router添加到现有项目中 目前,一个模型被传递到一个根组件,该根组件包含一个用于子导航的导航组件和一个主组件 我发现的react路由器示例只有一个子组件,在不重复两个布局代码的情况下更改多个子组件的最佳方法是什么?如果我理解正确,要实现这一点,您可以在路由中定义多个组件。您可以像这样使用它: //如果您有可插拔的路由器,请在路由器的上下文之外考虑它 //在“render”的部分中,可以这样做 ,应该对你有更多帮助 编辑: 根据@Luiz的评论: 在最新版本的路由器(v3)
我发现的react路由器示例只有一个子组件,在不重复两个布局代码的情况下更改多个子组件的最佳方法是什么?如果我理解正确,要实现这一点,您可以在
路由中定义多个组件。您可以像这样使用它:
//如果您有可插拔的路由器,请在路由器的上下文之外考虑它
//在“render”的部分中,可以这样做
,应该对你有更多帮助
编辑:
根据@Luiz的评论:
在最新版本的路由器(v3)中,组件位于props对象的根目录中
因此:
const{main,sidebar}=this.props.children;
变成:
const{main,sidebar}=this.props;
编辑:
在react路由器v4中,这可以通过以下方式实现(根据中提供的示例):
从“React”导入React
进口{
BrowserRouter作为路由器,
路线,,
链接
}从“反应路由器dom”
//每个逻辑“路由”有两个组件,一个用于
//侧边栏和一个用于主区域。我们想
//当
//路径与当前URL匹配。
常数路由=[
{路径:'/',
确切地说:是的,
侧边栏:()=>主页!,
main:()=>主页
},
{路径:'/bubblegum',
边栏:()=>泡泡糖!,
main:()=>泡泡糖
},
{路径:'/shoelaces',
侧边栏:()=>鞋带!,
主打:()=>鞋带
}
]
常量SidebarExample=()=>(
- 家
- 泡泡糖
- 鞋带
{routes.map((路由,索引)=>(
//可以在尽可能多的位置渲染渲染
//在你的应用程序中显示所需内容。它将随应用程序一起呈现
//与任何其他也与URL匹配的。
//所以,一个边栏或面包屑或其他任何东西
//这需要您渲染多个对象
//在同一个URL上的多个地方什么都不是
//多个s。
))}
{routes.map((路由,索引)=>(
//使用与相同的路径渲染多个
//以上,但这次是不同的组件。
))}
)
导出默认SidebarExample
请确保在此处查看新的React Router v4文档:该组件可以是返回JSX的函数
<Route>
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="Invite" component={()=>(<div><Home/><Invite/></div>)} />
</Route>
</Route>
()} />
2019+
执行此操作并避免滥用重新渲染的简单而干净的方法是(在react router v5上测试,需要在react router v4上确认):
与:
{routes.map((route,i)=>
r、 精确)}path={route.subRoutes.map(r=>r.path)}>
{route.subRoutes.map((subRoute,i)=>
)}
)}
再加上塞巴斯蒂安的回答,这对我来说似乎很有效,包括未找到的路由和动态子例程。下面的示例使myLayoutAuthenticated
和LayoutAnonymous
只渲染一次,而不是在使用相同布局的管线内的每个管线更改上。还添加了PageSettings
示例以显示此体系结构中的嵌套路由。希望这能帮助别人
(示例包括打字脚本)
const publicRoutes=[
{
键:“登录”,
路径:“/login”,
组件:PageLogin,
确切地说:是的
},
{
键:“注册”,
路径:“/signup”,
组件:PageSignup,
确切地说:是的
},
{
密钥:“忘记密码”,
路径:“/忘记密码”,
组件:PageForgotPassword,
确切地说:是的
}
];
const privaterotes=[
{
钥匙:“家”,
路径:“/”,
组件:PageHome,
确切地说:是的
},
{
键:“设置”,
路径:“/settings”,
component:PageSettings,//子路由在该组件中处理
精确:false//重要的是,PageSettings只是一个新的路由器交换机容器
}
];
//Routes.tsx
{privateRoutes.map(privateRouteProps=>(
))}
{publicRoutes.map(publicRouteProps=>(
))}
//LayoutAnonymous.tsx
从“React”导入React;
导出常量布局匿名:React.FC=props=>{
返回(
{props.children}
)
}
//LayoutAuthenticated.tsx
从“React”导入React;
从“../components/MainNavBar”导入{MainNavBar};
从“../components/MainContent”导入{MainContent};
导出常量布局验证:React.FC=props=>{
返回(
{props.children}
)
}
//PrivateRoute.tsx
从“React”导入React;
进口{
路线,,
重新使用
路由程序
}从“反应路由器dom”;
从“react redux”导入{useSelector};
接口道具扩展RouteProps{}
导出常量PrivateRoute:React.FC=props=>{
const isAuthenticated:boolean=useSelector((stores)=>stores.auth.isAuthenticated);
const{component:component,…restProps}=props;
如果(!组件)返回空值;
返回(
我被认证了(
) : (
)
}
/>
)
}
//PublicRoute.tsx
从“React”导入React;
从“react router dom”导入{Route,RouteProps,Redirect};
从“react redux”导入{useSelector};
接口道具扩展RouteProps{}
export const PublicRoute:React.FC=props=>{
常量isAuthenticated:boolean=useSelector((存储)=>stores.auth.isAuthenticated
<Switch>
<Route exact path={["/route1/:id/:token", "/"]}>
<Layout1>
<Route path="/route1/:id/:token" component={SetPassword} />
<Route exact path="/" component={SignIn} />
</Layout1>
</Route>
<Route path={["/route2"]}>
<Layout2>
<Route path="/route2" component={Home} />
</Layout2>
</Route>
</Switch>
const routes = [
{
layout:Layout1,
subRoutes:[
{
path:"/route1/:id/:token",
component:SetPassword
},
{
exact:true,
path:"/",
component:SignIn
},
]
},
{
layout:Layout2,
subRoutes:[
{
path:"/route2",
component:Home
},
]
}
];
<Switch>
{routes.map((route,i)=>
<Route key={i} exact={route.subRoutes.some(r=>r.exact)} path={route.subRoutes.map(r=>r.path)}>
<route.layout>
{route.subRoutes.map((subRoute,i)=>
<Route key={i} {...subRoute} />
)}
</route.layout>
</Route>
)}
</Switch>
// Routes.tsx
<Router>
<Switch>
<Route exact path={["/", "/settings", "/settings/*"]}>
<LayoutAuthenticated>
<Switch>
{privateRoutes.map(privateRouteProps => (
<PrivateRoute {...privateRouteProps} />
))}
</Switch>
</LayoutAuthenticated>
</Route>
<Route exact path={["/login", "/signup", "/forgot-password"]}>
<LayoutAnonymous>
<Switch>
{publicRoutes.map(publicRouteProps => (
<PublicRoute {...publicRouteProps} />
))}
</Switch>
</LayoutAnonymous>
</Route>
<Route path="*">
<LayoutAnonymous>
<Switch>
<Route component={PageNotFound} />
</Switch>
</LayoutAnonymous>
</Route>
</Switch>
</Router>
// LayoutAnonymous.tsx
import React from 'react';
export const LayoutAnonymous: React.FC<{}> = props => {
return (
<div>
{props.children}
</div>
)
}
// LayoutAuthenticated.tsx
import React from 'react';
import { MainNavBar } from '../components/MainNavBar';
import { MainContent } from '../components/MainContent';
export const LayoutAuthenticated: React.FC<{}> = props => {
return (
<>
<MainNavBar />
<MainContent>
{props.children}
</MainContent>
</>
)
}
// PrivateRoute.tsx
import React from "react";
import {
Route,
Redirect,
RouteProps
} from "react-router-dom";
import { useSelector } from "react-redux";
interface Props extends RouteProps {}
export const PrivateRoute: React.FC<Props> = props => {
const isAuthenticated: boolean = useSelector<any, any>((stores) => stores.auth.isAuthenticated);
const { component: Component, ...restProps } = props;
if (!Component) return null;
return (
<Route
{...restProps}
render={routeRenderProps =>
isAuthenticated ? (
<Component {...routeRenderProps} />
) : (
<Redirect
to={{
pathname: "/login",
state: { from: routeRenderProps.location }
}}
/>
)
}
/>
)
}
// PublicRoute.tsx
import React from "react";
import { Route, RouteProps, Redirect } from "react-router-dom";
import { useSelector } from "react-redux";
interface Props extends RouteProps {}
export const PublicRoute: React.FC<Props> = props => {
const isAuthenticated: boolean = useSelector<any, any>((stores) => stores.auth.isAuthenticated);
const { component: Component, ...restProps } = props;
if (!Component) return null;
return (
<Route
{...restProps}
render={routeRenderProps => (
!isAuthenticated ? (
<Component {...routeRenderProps} />
) : (
<Redirect
to={{
pathname: "/",
state: { from: routeRenderProps.location }
}}
/>
)
)}
/>
)
}
// PageSettings.tsx
import React from "react";
import { LinkContainer } from "react-router-bootstrap";
import Button from "react-bootstrap/Button";
import {
Switch,
useRouteMatch,
Redirect,
Switch
} from "react-router-dom";
import { PrivateRoute } from "../../routes/PrivateRoute";
import { PageSettingsProfile } from "./profile";
import { PageSettingsBilling } from "./billing";
import { PageSettingsAccount } from "./account";
export const PageSettings = () => {
const { path } = useRouteMatch();
return (
<div>
<h2>Settings</h2>
<Redirect strict from={path} to={`${path}/profile`} />
<LinkContainer to={`${path}/profile`}>
<Button>Profile</Button>
</LinkContainer>
<LinkContainer to={`${path}/billing`}>
<Button>Billing</Button>
</LinkContainer>
<LinkContainer to={`${path}/account`}>
<Button>Account</Button>
</LinkContainer>
<Switch>
<PrivateRoute path={`${path}/profile`} component={PageSettingsProfile} />
<PrivateRoute path={`${path}/billing`} component={PageSettingsBilling} />
<PrivateRoute path={`${path}/account`} component={PageSettingsAccount} />
</Switch>
</div>
);
};