여러 레이아웃으로 리액트 라우터 v4
퍼블릭 레이아웃 내에서 루트 중 일부를 렌더링하고 프라이빗 레이아웃 내에서 다른 루트를 렌더링하고 싶은데 깔끔한 방법이 있을까요?
분명히 효과가 없는 예이지만, 제가 찾고 있는 것을 대략적으로 설명해 주셨으면 합니다.
<Router>
<PublicLayout>
<Switch>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
</Switch>
</PublicLayout>
<PrivateLayout>
<Switch>
<Route exact path="/profile" component={ProfilePage} />
<Route exact path="/dashboard" component={DashboardPage} />
</Switch>
</PrivateLayout>
</Router>
레이아웃을 특정 경로로 전환하고 싶은데 새로운 리액트 라우터에서 어떻게 전환해야 합니까?
루트를 네스트 하면 기능하지 않게 되어, 다음의 에러가 표시됩니다.
You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored
편집: 레이아웃이 루트 그룹 전체를 랩하도록 하는 것은 동일한 프라이빗/퍼블릭 루트 그룹에 있는 한 레이아웃이 한 번만 렌더링됨을 의미합니다.예를 들어 레이아웃을 사용하여 각 페이지를 레이아웃으로 감싸면 페이지가 변경될 때마다 레이아웃이 서버에서 무언가를 가져와야 하는 경우에는 큰 문제가 됩니다.
이를 위해 Route 컴포넌트(레이아웃)에 추가 속성을 추가하는 간단한 컴포넌트를 만듭니다.
function RouteWithLayout({layout, component, ...rest}){
return (
<Route {...rest} render={(props) =>
React.createElement( layout, props, React.createElement(component, props))
}/>
);
}
그러면 당신의 경우 당신의 경로는 다음과 같습니다.
<Switch>
<RouteWithLayout layout={PublicLayout} path="/" component={HomePage}/>
<RouteWithLayout layout={PublicLayout} path="/about" component={AboutPage}/>
<RouteWithLayout layout={PrivateLayout} path="/profile" component={ProfilePage}/>
<RouteWithLayout layout={PrivateLayout} path="/dashboard" component={DashboardPage}/>
</Switch>
업데이트 2020
지금은 이 방법을 따르고 있습니다.이전에는 간단하게 투고했습니다.
const Pages = () => {
return (
<ReactRouter>
<Switch>
<Route path="/comingsoon" component={ComingSoon} exact />
<Route>
<MainLayout>
<Switch>
<Route path="/home" exact>
<Home />
</Route>
<Route path="/login" exact>
<Login />
</Route>
<Route path="/useraccount" exact>
<UserAccount />
</Route>
<Route path="/createaccount" exact>
<CreateAccount />
</Route>
<Route path="/contact" exact>
<Contact />
</Route>
<Route path="/about" exact>
<About />
</Route>
<Redirect path="/" exact to="/comingsoon" />
<Route path="*" exact component={NotFound} />
</Switch>
</MainLayout>
</Route>
</Switch>
</ReactRouter>
);
};
이와 같이 Main Layout은 곧 나올 페이지를 제외한 모든 것을 처리합니다.
오래된 답변
Typescript 를 사용하고 있는 경우, 다음의 리액트 레이아웃을 따를 필요가 있는 경우는, 다음과 같이 레이아웃을 선언할 수 있습니다.
import './Default.less';
import React from 'react';
import { Route } from "react-router-dom";
import { Sider } from './Components';
import { Notification } from 'Client/Components';
interface IDefaultProps {
component: any
path?: string;
exact?: boolean;
}
const Default: React.SFC<IDefaultProps> = (props) => {
const { component: Component, ...rest } = props;
return <Route {...rest} render={matchProps => (
<div className="defaultLayout">
<Sider />
<div className="defaultLayoutContent">
<Component {...matchProps} />
</div>
<Notification />
</div>
)} />
}
export default Default;
그리고 다음과 같이 루트를 선언합니다.
import React from 'react';
import { Route } from 'react-router-dom';
import { DefaultLayout } from 'Client/Layout';
import { Dashboard, Matters, Schedules, Students } from './Containers';
export const routes = <div>
<DefaultLayout exact path="/" component={Dashboard} />
<DefaultLayout path="/matters" component={Matters} />
<DefaultLayout path="/schedules" component={Schedules} />
<DefaultLayout path="/students" component={Students} />
</div>;
2019+
검색 후 깨끗하고 효율적인 방법(남용적인 재렌더링 방지):
<Route exact path={["/about", "/"]}>
<PublicLayout>
<Route exact path="/" component={HomePage} />
<Route path="/about" component={AboutPage} />
</PublicLayout>
</Route>
<Route path={["/profile", "/dashboard"]}>
<PrivateLayout>
<Route path="/profile" component={ProfilePage} />
<Route path="/dashboard" component={DashboardPage} />
</PrivateLayout>
</Route>
aslo, 리팩터링 할 수 있습니다.완전한 답변을 참조해 주세요.https://stackoverflow.com/a/57358661/3437790
경로 파일에 레이아웃이 없는 것 같아요.
경로를 깨끗한 상태로 유지합니다.
<Route exact path="/" component="HomePage" />
★★★★★★★★★★★★★★★★★★★★★★.HomePage
렌더링된 내용을 선택한 레이아웃으로 줄 바꿈:
...
render() {
<PublicLayout>
<h1>Home page!</h1>
</PublicLayout>
}
이렇게 하면 루트는 매우 깨끗한 상태를 유지할 수 있습니다.또, 양쪽의 레이아웃(예를 들면 404 페이지)을 서포트하는 루트를 간단하게 표시할 수 있습니다.
이 질문이 나온 곳마다 글을 쓰도록 하겠습니다. 혹시 다른 곳에서 보셨다면 죄송합니다.한동안 힘들었기 때문에 하고 있는 것일 뿐이고, 가능한 한 이 솔루션을 보급할 가치가 있다고 생각합니다.말은 충분해, 이게 내가 한 일이야, 내 생각엔 꽤 자기 설명적인 것 같아.마법처럼 작동하며 타이핑도 매우 쉽습니다.
const withLayout = (LayoutComp, ComponentComp) => <LayoutComp><ComponentComp /></LayoutComp>;
const withDefaultLayout = (ComponentComp) => () => withLayout(Layout, ComponentComp);
const withEmptyLayout = (ComponentComp) => () => withLayout(EmptyLayout, ComponentComp);
export const routes = <div>
<Switch>
<Route path="/" exact render={withDefaultLayout(Home)} />
<Route path='/subscriptions' render={withDefaultLayout(SubscriptionsWrapped)} />
<Route path='/callback' render={withEmptyLayout(AuthCallback)} />
<Route path='/welcome/initial' render={withEmptyLayout(Start)} />
</Switch>
</div>;
Florians의 답변을 시험해 보았습니다만, 각 루트에 대해 Layout의 개별 인스턴스가 생성되므로 탭 슬라이딩과 같은 내비게이션 전환은 모두 중지됩니다.
좀 더 우아한 솔루션을 원하지만 v4에서 앱을 다시 사용할 수 있게 되었습니다.
루트를 랩할 대상을 결정하는 컴포넌트를 가리키는 하나의 루트를 정의합니다.
<Router>
<Route component={AppWrap} />
</Router>
AppWrap에서 다음과 같은 작업을 수행합니다.
var isPrivateLayout;
for (var path of listOfPrivateLayoutPaths) {
if (this.props.location.pathname == path) {
isPrivateLayout= true;
}
}
if (isPrivateLayout) {
return <PrivateLayout>
(routes)
</PrivatelyLayout>
} else {
return <PublicLayout>
(routes)
</PublicLayout>;
}
Route Config는 이를 보다 명확하게 표현하기 위해 사용할 수 있습니다.
업데이트: 다른 방법으로 해결했습니다만, 앱의 다른 부분을 /app 또는 /admin으로 네임스페이스를 지정하도록 강요하는 경우.
UserRoutes, AdminRoutes 및 PublicRoutes의 각 컴포넌트는 기본적으로 큰 스위치컴포넌트로 특정 레이아웃이 루트에 있습니다.
그 외관은 다음과 같습니다.
<Router>
<Switch>
<Route path="/app" render={props => <UserRoutes {...props} />} />
<Route path="/admin" render={props => <AdminRoutes {...props} />} />
<Route path="/" render={props => <PublicRoutes {...props} />} />
</Switch>
</Router>
구식: 각 경로의 렌더 소품을 사용하는 것이 하나의 해결책이지만, 매우 번거로운 것 같습니다.
<Router>
<Switch>
<Route
path="/"
render={() => <PublicLayout><HomePage /></PublicLayout>}
/>
<Route
path="/about"
render={() => <PublicLayout><AboutPage /></PublicLayout>}
/>
<Route
path="/profile"
render={() => <PrivateLayout><ProfilePage /></PrivateLayout>}
/>
<Route
path="/dashboard"
render={() => <PrivateLayout><DashboardPage /></PrivateLayout>}
/>
</Switch>
</Router>
아이디어는 Zaptree와 동일하지만 es6 구문을 사용하고 react-router의 Route 컴포넌트 대신 사용할 수 있도록 체크를 추가했습니다.
새 컴포넌트(예: /src/components/Route/index.js)를 만듭니다.
import React, {Component} from 'react'
import PropTypes from 'prop-types'
import {Route as ReactRoute} from 'react-router'
class Route extends Component {
static propTypes = {
component: PropTypes.func.isRequired,
layout: PropTypes.func,
path: PropTypes.string,
exact: PropTypes.bool
}
render = () => {
const {component, layout, path, exact} = this.props
let routeComponent = props => React.createElement(component, props)
if (layout) {
routeComponent = props =>
React.createElement(layout, props, React.createElement(component, props))
}
return <ReactRoute path={path} exact={exact} render={routeComponent}/>
}
}
export default Route
작성한 Route 컴포넌트를 사용합니다.
import Route from 'components/Route/'
...
<Router history={createHistory()}>
<Switch>
<Route exact path='/' layout={PublicLayout} component={HomePage}/>
<Route exact path='/' layout={PrivateLayout} component={ProfilePage}/>
<Route path='/logins' component={Login}/>
</Switch>
</Router>
Route 컴포넌트의 렌더 프로포넌트를 사용합니다.이렇게 해도 루트 변경 시마다 레이아웃컴포넌트를 마운트 및 마운트 할 수 없습니다.자세한 내용은 여기를 참조하십시오.
2개의 레이아웃 컴포넌트 Primary.js와 Secondary.js가 있다고 합니다.
App.js 렌더링 방법에서는 반환만 하면 됩니다.
<BrowserRouter>
<Switch>
<Route path='/login' render={() => <Secondary><Login/></Secondary>} />
<Route path='/dashboard' render={() => <Primary><Dashboard/></Primary>} />
</Switch>
</BrowserRouter>
세분화하기 위해 페이지 구성요소를 레이아웃으로 줄바꿈하는 고차 구성요소 레이아웃 구성요소를 정의할 수도 있습니다.(테스트되지 않음)
<Route to='/login' render={() => Secondary(Login)}
@Qop은 맞습니다만, 새로운 리액트라우터에서는 스위치 내부에 루트 패스가 첫 번째 루트로 설정되어 있는 경우 루트 패스는 항상 일치하므로 다음 루트는 표시되지 않습니다.루트 경로를 마지막에 넣어야 합니다.
<Switch>
<RouteWithLayout layout={PublicLayout} path="/about" component={AboutPage}/>
<RouteWithLayout layout={PrivateLayout} path="/profile" component={ProfilePage}/>
<RouteWithLayout layout={PrivateLayout} path="/dashboard" component={DashboardPage}/>
<RouteWithLayout layout={PublicLayout} path="/" component={HomePage}/>
</Switch>
@Zaptree와 같은 아이디어
레이아웃
function PublicLayout(props) {
return (
<Route {...props} />
);
}
function PrivateLayout(props) {
return (
<Route {...props} />
);
}
루트
<Switch>
<PublicLayout exact path="/" component={HomePage} />
<PrivateLayout path="/profile" component={ProfilePage} />
<Route path="/callback" component={NoLayoutPage} />
</Switch>
이 솔루션은 효과가 있습니다.
<Router>
<Switch>
<PublicLayout>
<Route exact path="/" component={HomePage} />
<Route exact path="/about" component={AboutPage} />
</PublicLayout>
</Switch>
<Switch>
<PrivateLayout>
<Route exact path="/profile" component={ProfilePage} />
<Route exact path="/dashboard" component={DashboardPage} />
</PrivateLayout>
</Switch>
</Router>
언급URL : https://stackoverflow.com/questions/42862028/react-router-v4-with-multiple-layouts
'prosource' 카테고리의 다른 글
표준 시간대에 맞게 조정되는 각도 UI DatePicker (0) | 2023.03.19 |
---|---|
TypeScript 함수에서 클래스를 반환하려면 어떻게 해야 합니까? (0) | 2023.03.19 |
Typescript에서 인터페이스를 구현할 때 개인 속성을 정의하는 방법은 무엇입니까? (0) | 2023.03.19 |
Vue Axios CORS 정책:'액세스 제어-허용-발신원' 없음 (0) | 2023.03.19 |
Angular에서 'pathmatch: full'은 무엇이며 어떤 효과가 있습니까? (0) | 2023.03.19 |