switch react example exact reactjs react-router

reactjs - example - react router match



React Router v4 con múltiples diseños (10)

@Qop es correcto, sin embargo, en el nuevo React Router noté que si tiene su ruta de acceso raíz dentro del switch como la primera ruta, siempre coincidirá con ella y, por lo tanto, nunca mostrará las siguientes rutas. Deberías poner la ruta raíz al final.

<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>

Me gustaría mostrar algunas de mis rutas dentro de mi diseño público, y algunas otras rutas dentro de mi diseño privado, ¿hay alguna forma limpia de hacerlo?

Un ejemplo que obviamente no funciona, pero espero que explique más o menos lo que estoy buscando:

<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>

Me gustaría que el diseño cambie para ciertas rutas, ¿cómo hago esto con el nuevo enrutador de reacción?

Las rutas de anidamiento ya no funcionan y me da este error:

You should not use <Route component> and <Route children> in the same route; <Route children> will be ignored

Editar: tener diseños que envuelvan grupos enteros de rutas también significa que esos diseños solo se procesan una vez, siempre y cuando permanezca en el mismo grupo privado / público de rutas. Esto es un gran problema si su diseño tiene que recuperar algo de su servidor, por ejemplo, como sucedería en cada cambio de página si envuelve cada página con un diseño.


Actualización: lo resolví de otra manera, pero si te obliga a hacer un espacio de nombre en las diferentes partes de tu aplicación con / app o / admin por ejemplo.

Cada uno de los componentes UserRoutes, AdminRoutes y PublicRoutes son básicamente componentes de Switch grandes con el diseño específico en su raíz.

Así es como se ve:

<Router> <Switch> <Route path="/app" render={props => <UserRoutes {...props} />} /> <Route path="/admin" render={props => <AdminRoutes {...props} />} /> <Route path="/" render={props => <PublicRoutes {...props} />} /> </Switch> </Router>

Antiguo: una solución sería utilizar el soporte de renderizado de cada Ruta, pero parece realmente engorroso:

<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>


Esta solución funcionará.

<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>


Intenté la respuesta de Florians, pero eso no fue suficiente para mí, ya que reaccionaré para crear una instancia separada de su Diseño para cada ruta, por lo que se eliminarán las transiciones de navegación, como el desplazamiento de una pestaña.

Espero una solución más elegante, pero esto ha hecho que mi aplicación vuelva a funcionar con v4.

Defina una ruta que apunte a un componente que decidirá en qué envolver la ruta

<Router> <Route component={AppWrap} /> </Router>

En AppWrap haz algo como lo siguiente

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

La configuración de ruta podría utilizarse para una representación más limpia de esto, no estoy seguro.


La idea es la misma que la de Zaptree pero utilizando la sintaxis de es6 y las comprobaciones agregadas para que pueda usarse en lugar del componente Route del enrutador de reacción

Cree un nuevo componente, diga /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

Utilice el componente de ruta creado:

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>


La misma idea con @Zaptree

Diseño

function PublicLayout(props) { return ( <Route {...props} /> ); } function PrivateLayout(props) { return ( <Route {...props} /> ); }

Rutas

<Switch> <PublicLayout exact path="/" component={HomePage} /> <PrivateLayout path="/profile" component={ProfilePage} /> <Route path="/callback" component={NoLayoutPage} /> </Switch>


Lo que he hecho para esto es crear un componente simple que agregue una propiedad adicional al componente de Ruta que es el diseño:

function RouteWithLayout({layout, component, ...rest}){ return ( <Route {...rest} render={(props) => React.createElement( layout, props, React.createElement(component, props)) }/> ); }

Entonces en tu caso tus rutas se verían así.

<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>


No creo que los diseños pertenezcan a los archivos de ruta.

Mantener la ruta limpia, es decir:

<Route exact path="/" component="HomePage" />

Luego, en el componente HomePage , envuelva el contenido representado en el diseño que elija:

... render() { <PublicLayout> <h1>Home page!</h1> </PublicLayout> }

De esta manera, las rutas se mantienen súper limpias, y además tiene una forma fácil de mostrar rutas que deberían admitir ambos diseños (por ejemplo, 404 páginas).


Si está utilizando Typescript y desea seguir simonsmith.io/reusing-layouts-in-react-router-4 , puede declarar su diseño de la siguiente manera:

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;

Y declarar rutas como esta:

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


Voy a escribir esto en todas partes donde se hizo esta pregunta, lo siento si la has visto en otra parte. Solo lo hago porque he luchado por un tiempo y creo que vale la pena difundir esta solución tanto como sea posible. Suficientes palabras, esto es lo que hice, creo que es bastante explicativo. Funciona como un encanto y es muy fácil de escribir.

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