레이아웃 페이지 또는 페이지당 여러 구성 요소와 함께 반응 라우터 사용
기존 프로젝트에 리액션 라우터를 추가한다.
현재 모델은 서브 내비게이션용 내비게이션 구성 요소와 메인 구성 요소를 포함하는 루트 구성 요소로 전달된다.
내가 찾은 리액션 라우터의 예로는 하위 구성요소가 하나뿐인데, 둘 다에서 레이아웃 코드를 반복하지 않고 여러 하위 구성요소를 변경하는 가장 좋은 방법은 무엇인가?
만약 내가 당신을 정확히 이해했다면, 당신은 당신의 안에 여러 구성요소를 정의 할 것이다.Route
. 다음과 같이 사용할 수 있다.
// think of it outside the context of the router, if you had pluggable
// portions of your `render`, you might do it like this
<App children={{main: <Users/>, sidebar: <UsersSidebar/>}}/>
// So with the router it looks like this:
const routes = (
<Route component={App}>
<Route path="groups" components={{main: Groups, sidebar: GroupsSidebar}}/>
<Route path="users" components={{main: Users, sidebar: UsersSidebar}}>
<Route path="users/:userId" component={Profile}/>
</Route>
</Route>
)
class App extends React.Component {
render () {
const { main, sidebar } = this.props;
return (
<div>
<div className="Main">
{main}
</div>
<div className="Sidebar">
{sidebar}
</div>
</div>
)
}
}
class Users extends React.Component {
render () {
return (
<div>
{/* if at "/users/123" `children` will be <Profile> */}
{/* UsersSidebar will also get <Profile> as this.props.children,
so its a little weird, but you can decide which one wants
to continue with the nesting */}
{this.props.children}
</div>
)
}
}
편집: @Luiz의 설명에 따라:
라우터(v3)의 최신 버전에서 구성 요소는 소품 개체의 루트에 있음
자:
const { main, sidebar } = this.props.children;
다음이 됨:
const { main, sidebar } = this.props;
편집: 리액터 v4에서 다음과 같이 수행할 수 있다(새로운 문서에 제공된 예에 따름).
import React from 'react'
import {
BrowserRouter as Router,
Route,
Link
} from 'react-router-dom'
// Each logical "route" has two components, one for
// the sidebar and one for the main area. We want to
// render both of them in different places when the
// path matches the current URL.
const routes = [
{ path: '/',
exact: true,
sidebar: () => <div>home!</div>,
main: () => <h2>Home</h2>
},
{ path: '/bubblegum',
sidebar: () => <div>bubblegum!</div>,
main: () => <h2>Bubblegum</h2>
},
{ path: '/shoelaces',
sidebar: () => <div>shoelaces!</div>,
main: () => <h2>Shoelaces</h2>
}
]
const SidebarExample = () => (
<Router>
<div style={{ display: 'flex' }}>
<div style={{
padding: '10px',
width: '40%',
background: '#f0f0f0'
}}>
<ul style={{ listStyleType: 'none', padding: 0 }}>
<li><Link to="/">Home</Link></li>
<li><Link to="/bubblegum">Bubblegum</Link></li>
<li><Link to="/shoelaces">Shoelaces</Link></li>
</ul>
{routes.map((route, index) => (
// You can render a <Route> in as many places
// as you want in your app. It will render along
// with any other <Route>s that also match the URL.
// So, a sidebar or breadcrumbs or anything else
// that requires you to render multiple things
// in multiple places at the same URL is nothing
// more than multiple <Route>s.
<Route
key={index}
path={route.path}
exact={route.exact}
component={route.sidebar}
/>
))}
</div>
<div style={{ flex: 1, padding: '10px' }}>
{routes.map((route, index) => (
// Render more <Route>s with the same paths as
// above, but different components this time.
<Route
key={index}
path={route.path}
exact={route.exact}
component={route.main}
/>
))}
</div>
</div>
</Router>
)
export default SidebarExample
여기서 새로운 Ract Router v4 문서를 확인하십시오. https://reacttraining.com/react-router/
2019 +
간단하고 깨끗한 방법으로 이를 수행하고 악의적인 재렌딩을 방지할 수 있는 방법은 다음과 같다(반응 라우터 v5에서 테스트, 반응 라우터 v4에서 확인 필요).
<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>
세바스티앙의 대답에 덧붙여 말하자면, 이것은 찾지 못한 경로와 역동적인 서브루트를 포함한 나에게 효과가 있는 것 같다.아래 예들은 나를 만든다.LayoutAuthenticated
그리고LayoutAnonymous
동일한 레이아웃을 사용하는 경로 내의 모든 경로 변경에 대해 한 번만 렌더링하십시오.또한 다음 항목도 추가됨PageSettings
이 아키텍처 내에 중첩된 경로를 표시하는 예제.이것이 다른 사람들에게 도움이 되기를!
(예: TypeScript 포함)
const publicRoutes = [
{
key: "login",
path: "/login",
component: PageLogin,
exact: true
},
{
key: "signup",
path: "/signup",
component: PageSignup,
exact: true
},
{
key: "forgot-password",
path: "/forgot-password",
component: PageForgotPassword,
exact: true
}
];
const privateRoutes = [
{
key: "home",
path: "/",
component: PageHome,
exact: true
},
{
key: "settings",
path: "/settings",
component: PageSettings, // sub routing is handled in that component
exact: false // important, PageSettings is just a new Router switch container
}
];
// 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>
);
};
이 부품은 JSX를 반환하는 기능이 될 수 있다.
<Route>
<Route path="/" component={App}>
<IndexRoute component={Home} />
<Route path="Invite" component={()=>(<div><Home/><Invite/></div>)} />
</Route>
</Route>
"너무 복잡하게 만드는 대신 라우터 태그 내부에 두 개의 스위치 문을 직접 사용할 수 있다"고 말했다.
<div className= {classes.root}>
<CssBaseline></CssBaseline>
<Router>
<Switch>
<Route path="/" exact component={Header}></Route>
<Route path="/login" component={Login}></Route>
</Switch>
<Switch>
<Route path="/" exact component={Checkout}></Route>
</Switch>
</Router>
</div>
'programing' 카테고리의 다른 글
Windows에서 여러 Python 버전을 실행하는 방법 (0) | 2022.03.11 |
---|---|
라우터 v4 모달 반응 (0) | 2022.03.11 |
Nuxtjs는 '분할을 위해 / 를 많이 던지는 것은 더 이상 사용되지 않으며 다트 사스 2.0.0에서 제거될 것이다.` (0) | 2022.03.11 |
어떻게 분단을 부동의 지점으로 강제할 수 있을까?0으로 반올림하는 중인가? (0) | 2022.03.11 |
반응-축소 사용선택자 형식 상태 유형 (0) | 2022.03.11 |