Tengo la siguiente estructura para mi aplicación React.js usando React Router :
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var Index = React.createClass({
render: function () {
return (
<div>
<header>Some header</header>
<RouteHandler />
</div>
);
}
});
var routes = (
<Route path="/" handler={Index}>
<Route path="comments" handler={Comments}/>
<DefaultRoute handler={Dashboard}/>
</Route>
);
ReactRouter.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
Quiero pasar algunas propiedades al Comments
componente.
(normalmente haría esto como <Comments myprop="value" />
)
¿Cuál es la forma más fácil y correcta de hacerlo con React Router?
Desde la nueva versión, es posible pasar accesorios directamente a través del Route
componente, sin usar un Wrapper. Por ejemplo, usando render
prop .
Componente:
class Greeting extends React.Component {
render() {
const {text, match: {params}} = this.props;
const {name} = params;
return (
<React.Fragment>
<h1>Greeting page</h1>
<p>
{text} {name}
</p>
</React.Fragment>
);
}
}
Uso:
<Route path="/greeting/:name" render={(props) => <Greeting text="Hello, " {...props} />} />
Mi forma preferida es envolver el Comments
componente y pasar el contenedor como controlador de ruta.
Este es su ejemplo con los cambios aplicados:
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var CommentsWrapper = React.createClass({
render: function () {
return (
<Comments myprop="myvalue"/>
);
}
});
var Index = React.createClass({
render: function () {
return (
<div>
<header>Some header</header>
<RouteHandler/>
</div>
);
}
});
var routes = (
<Route path="/" handler={Index}>
<Route path="comments" handler={CommentsWrapper}/>
<DefaultRoute handler={Dashboard}/>
</Route>
);
ReactRouter.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
Si prefieres no escribir envoltorios, supongo que podrías hacer esto:
class Index extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<h1>
Index - {this.props.route.foo}
</h1>
);
}
}
var routes = (
<Route path="/" foo="bar" component={Index}/>
);
Copiando de los comentarios de ciantic en la respuesta aceptada:
<Route path="comments" component={() => (<Comments myProp="value" />)}/>
Esta es la solución más elegante en mi opinión. Funciona. Me ayudó.
Esta es la solución de Rajesh , sin los inconvenientes react-router - pasar accesorios al componente del controlador , y actualizada para React Router 4.
El código sería así:
<Route path="comments" render={(props) => <Comments myProp="value" {...props}/>}/>
Tenga en cuenta que utilizo en render
lugar de component
. El motivo es evitar un montaje no deseado . También paso el props
a ese método, y uso los mismos accesorios en el componente Comentarios con el operador de extensión de objetos (propuesta de ES7).
Solo un seguimiento de la respuesta de ColCh. Es bastante fácil abstraer la envoltura de un componente:
var React = require('react');
var wrapComponent = function(Component, props) {
return React.createClass({
render: function() {
return React.createElement(Component, props);
}
});
};
<Route path="comments" handler={wrapComponent(Comments, {myprop: value})}/>
Todavía no he probado esta solución, por lo que cualquier comentario es importante.
Es importante tener en cuenta que con este método, cualquier accesorio enviado a través del enrutador (como params) se sobrescribe / elimina.
Puede pasar accesorios pasándolos a <RouteHandler>
(en v0.13.x) o al propio componente de ruta en v1.0;
// v0.13.x
<RouteHandler/>
<RouteHandler someExtraProp={something}/>
// v1.0
{this.props.children}
{React.cloneElement(this.props.children, {someExtraProp: something })}
(de la guía de actualización en https://github.com/rackt/react-router/releases/tag/v1.0.0 )
Todos los cuidadores de niños recibirán el mismo conjunto de accesorios; esto puede ser útil o no, según las circunstancias.
Con ES6, puede hacer envoltorios de componentes en línea:
<Route path="/" component={() => <App myProp={someValue}/>} >
Si necesita pasar niños:
<Route path="/" component={(props) => <App myProp={someValue}>{props.children}</App>} >
ahora hay una nueva forma de hacer esto, aunque muy similar al método anterior.
import { Match, Link, Miss } from 'react-router';
import Homepage from './containers/Homepage';
const route = {
exactly: true,
pattern: '/',
title: `${siteTitle} - homepage`,
component: Homepage
}
<Match { ...route } render={(props) => <route.component {...props} />} />
PD: Esto solo funciona en la versión alfa y se eliminó después de la versión alfa v4. En la última v4, es una vez más, con la ruta y los accesorios exactos.
react-lego, una aplicación de ejemplo contiene código que hace exactamente esto en route.js en su rama react-router-4
Aquí está la solución más limpia que he encontrado (React Router v4):
<Route
path="/"
component={props => <MyComponent {...props} foo="lol" />}
/>
MyComponent
todavía tiene props.match
y props.location
, y tiene props.foo === "lol"
.
Envuélvalo con un componente de función sin estado:
<Router>
<Route
path='/'
component={({children}) =>
<MyComponent myProp={'myVal'}>{children}</MyComponent/>
}/>
</Router>
También puede usar el mixin RouteHandler para evitar el componente contenedor y pasar más fácilmente el estado del padre como accesorios:
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var RouteHandler = require('react-router/modules/mixins/RouteHandler');
var Index = React.createClass({
mixins: [RouteHandler],
render: function () {
var handler = this.getRouteHandler({ myProp: 'value'});
return (
<div>
<header>Some header</header>
{handler}
</div>
);
}
});
var routes = (
<Route path="/" handler={Index}>
<Route path="comments" handler={Comments}/>
<DefaultRoute handler={Dashboard}/>
</Route>
);
ReactRouter.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
Puede pasar accesorios a través de la <RouterHandler/>
siguiente manera:
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var Index = React.createClass({
render: function () {
var props = this.props; // or possibly this.state
return (
<div>
<header>Some header</header>
<RouteHandler {...props} />
</div>
);
}
});
La desventaja de esto es que estás pasando accesorios indiscriminadamente. Por Comments
lo tanto, puede terminar recibiendo accesorios que realmente están destinados a un componente diferente según la configuración de sus rutas. No es un gran problema ya que props
es inmutable, pero esto puede ser problemático si dos componentes diferentes esperan un prop con nombre foo
pero con valores diferentes.
En 1.0 y 2.0 puede usar createElement
prop of Router
para especificar exactamente cómo crear su elemento de destino. Fuente de documentación
function createWithDefaultProps(Component, props) {
return <Component {...props} myprop="value" />;
}
// and then
<Router createElement={createWithDefaultProps}>
...
</Router>
Solución React Router v 4
Me topé con esta pregunta hoy y este es el patrón que utilizo. Con suerte, esto es útil para cualquiera que busque una solución más actual.
No estoy seguro de si esta es la mejor solución, pero este es mi patrón actual para esto. Normalmente tengo un directorio Core donde guardo mis componentes de uso común con sus configuraciones relevantes (cargadores, modales, etc.), e incluyo un archivo como este:
import React from 'react'
import { Route } from 'react-router-dom'
const getLocationAwareComponent = (component) => (props) => (
<Route render={(routeProps) => React.createElement(component,
{...routeProps, ...props})}/>
)
export default getLocationAwareComponent
Luego, en el archivo en cuestión, haré lo siguiente:
import React from 'react'
import someComponent from 'components/SomeComponent'
import { getLocationAwareComponent } from 'components/Core/getLocationAwareComponent'
const SomeComponent = getLocationAwareComponent(someComponent)
// in render method:
<SomeComponent someProp={value} />
Notarás que importo la exportación predeterminada de mi componente como humilde camel-case, lo que me permite nombrar el nuevo componente con reconocimiento de ubicación en CamelCase para poder usarlo normalmente. Aparte de la línea de importación adicional y la línea de asignación, el componente se comporta como se esperaba y recibe todos sus accesorios normalmente, con la adición de todos los accesorios de ruta. Por lo tanto, puedo redirigir felizmente desde los métodos del ciclo de vida de los componentes con this.props.history.push (), verificar la ubicación, etc.
¡Espero que esto ayude!
También puede combinar es6 y funciones sin estado para obtener un resultado mucho más limpio:
import Dashboard from './Dashboard';
import Comments from './Comments';
let dashboardWrapper = () => <Dashboard {...props} />,
commentsWrapper = () => <Comments {...props} />,
index = () => <div>
<header>Some header</header>
<RouteHandler />
{this.props.children}
</div>;
routes = {
component: index,
path: '/',
childRoutes: [
{
path: 'comments',
component: dashboardWrapper
}, {
path: 'dashboard',
component: commentsWrapper
}
]
}
Para react router 2.x.
const WrappedComponent = (Container, propsToPass, { children }) => <Container {...propsToPass}>{children}</Container>;
y en tus rutas ...
<Route path="/" component={WrappedComponent.bind(null, LayoutContainer, { someProp })}>
</Route>
asegúrese de que la tercera parámetro es un objeto como: { checked: false }
.
El problema con React Router es que procesa sus componentes y, por lo tanto, evita que pase accesorios. El enrutador de navegación , por otro lado, le permite renderizar sus propios componentes. Eso significa que no tiene que pasar por ningún obstáculo para pasar los accesorios como el siguiente código y el espectáculo de JsFiddle que lo acompaña .
var Comments = ({myProp}) => <div>{myProp}</div>;
var stateNavigator = new Navigation.StateNavigator([
{key:'comments', route:''}
]);
stateNavigator.states.comments.navigated = function(data) {
ReactDOM.render(
<Comments myProp="value" />,
document.getElementById('content')
);
}
stateNavigator.start();
Utilice el componente con o sin enrutador según la respuesta de Rajesh Naroth.
class Index extends React.Component {
constructor(props) {
super(props);
}
render() {
const foo = (this.props.route) ? this.props.route.foo : this.props.foo;
return (
<h1>
Index - {foo}
</h1>
);
}
}
var routes = (
<Route path="/" foo="bar" component={Index}/>
);
O puedes hacerlo de esta manera:
export const Index = ({foo, route}) => {
const content = (foo) ? foo : (route) ? route.foo : 'No content found!';
return <h1>{content}</h1>
};
Utilice la solución como a continuación y esto funciona en v3.2.5.
<Route
path="/foo"
component={() => (
<Content
lang="foo"
meta={{
description: lang_foo.description
}}
/>
)}
/>
o
<Route path="/foo">
<Content
lang="foo"
meta={{
description: lang_foo.description
}}
/>
</Route>
Ya he respondido a esto Reaccionar los accesorios de paso del enrutador para enrutar el componente .
Aquí hay algunas formas en las que puede pasar accesorios a un componente de ruta.
Con react-router v5, podemos crear rutas envolviendo con un componente, de modo que podamos pasar fácilmente accesorios al componente deseado como este.
<Route path="/">
<Home name="Sai" />
</Route>
De manera similar, puede usar la propiedad de los niños en v5.
<Route path="/" children={ <Home name="Sai" />} />
Si está usando react-router v4, puede pasarlo usando la función de renderizado.
<Route path="/" render={() => <Home name="Sai" />} />
(publicado originalmente en https://reactgo.com/react-router-pass-props/ )
para el react-router 2.5.2, la solución es muy fácil:
//someConponent
...
render:function(){
return (
<h1>This is the parent component who pass the prop to this.props.children</h1>
{this.props.children && React.cloneElement(this.props.children,{myProp:'value'})}
)
}
...
Usando un componente de ruta personalizado , esto es posible en React Router v3.
var Dashboard = require('./Dashboard');
var Comments = require('./Comments');
var routes = (
<Route path="/" handler={Index}>
<MyRoute myprop="value" path="comments" handler={Comments}/>
<DefaultRoute handler={Dashboard}/>
</Route>
);
En cuanto al <MyRoute>
código del componente, debería ser algo como:
import React from 'react';
import { Route } from 'react-router';
import { createRoutesFromReactChildren } from 'react-router/lib//RouteUtils';
const MyRoute = () => <div><MyRoute> elements are for configuration only and should not be rendered</div>;
MyRoute.createRouteFromReactElement = (element, parentRoute) => {
const { path, myprop } = element.props;
// dynamically add crud route
const myRoute = createRoutesFromReactChildren(
<Route path={path} />,
parentRoute
)[0];
// higher-order component to pass myprop as resource to components
myRoute.component = ({ children }) => (
<div>
{React.Children.map(children, child => React.cloneElement(child, { myprop }))}
</div>
);
return myRoute;
};
export default MyRoute;
Para obtener más detalles sobre el enfoque del componente de ruta personalizado, consulte la publicación de mi blog sobre el tema: http://marmelab.com/blog/2016/09/20/custom-react-router-component.html
esta es probablemente la mejor manera de usar react-router-dom con un controlador de cookies
en index.js
import React, { Component } from 'react'
import {Switch,Route,Redirect} from "react-router-dom"
import {RouteWithLayout} from "./cookieCheck"
import Login from "../app/pages/login"
import DummyLayout from "../app/layouts/dummy"
import DummyPage from "../app/pages/dummy"
export default ({props})=>{
return(
<Switch>
<Route path="/login" component={Login} />
<RouteWithLayout path="/dummy" layout={DummyLayout} component={DummyPage}
{...props}/>
<Redirect from="/*" to="/login" />
</Switch>
)
}
y usa una cookieCheck
import React , {createElement} from 'react'
import {Route,Redirect} from "react-router-dom"
import {COOKIE,getCookie} from "../services/"
export const RouteWithLayout = ({layout,component,...rest})=>{
if(getCookie(COOKIE)==null)return <Redirect to="/login"/>
return (
<Route {...rest} render={(props) =>
createElement(layout, {...props, ...rest}, createElement(component,
{...props, ...rest}))
}
/>
)
}
class App extends Component {
constructor(props){
super(props);
this.state = {
data:null
}
}
componentDidMount(){
database.ref().on('value', (snapshot) =>{
this.setState({
data : snapshot.val()
})
});
}
render(){
// const { data } = this.state
return (
<BrowserRouter>
<Switch>
<Route exact path = "/" component = { LandingPage } />
<Route
path='/signup'
render = { () => <Signup data = {this.state.data} />} />
</Switch>
</BrowserRouter>
);
}
};
export default App;
La estrella de HGTV, Christina Hall, revela que le diagnosticaron envenenamiento por mercurio y plomo, probablemente debido a su trabajo como manipuladora de casas.
Recientemente salió a la luz un informe policial que acusa a la estrella de 'Love Is Blind', Brennon, de violencia doméstica. Ahora, Brennon ha respondido a los reclamos.
Conozca cómo Wynonna Judd se dio cuenta de que ahora es la matriarca de la familia mientras organizaba la primera celebración de Acción de Gracias desde que murió su madre, Naomi Judd.
Descubra por qué un destacado experto en lenguaje corporal cree que es fácil trazar "tales paralelismos" entre la princesa Kate Middleton y la princesa Diana.
Los inodoros arrojan columnas de aerosol invisibles con cada descarga. ¿Como sabemos? La prueba fue capturada por láseres de alta potencia.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
¿Sigue siendo efectivo ese lote de repelente de insectos que te quedó del verano pasado? Si es así, ¿por cuánto tiempo?
Si este tráiler de pesadilla de la temporada más reciente de Great British Bake Off te asustó y te hizo no volver a ver el programa, es posible que tengas suerte: PBS no ha decidido si se transmitirá o no la última temporada en los Estados Unidos. actualización, para aquellos que no siguen sin aliento este tipo de drama de nicho: el presentador Paul Hollywood y la hermosa carpa llena de batidoras de colores pastel y cuadros se trasladaron de la BBC al Canal 4; Mary Berry, Sue Perkins y Mel Giedroyc renunciaron.
Foto: Netflix Oh, Hello On Broadway (Netflix): Después de llegar a Broadway el año pasado, los dos locos del Upper West Side interpretados por John Mulaney y Nick Kroll finalmente llegaron a Netflix. El especial consta del espectáculo en el escenario, algunos momentos entre bastidores y un invitado muy especial de “Too Much Tuna”.
¿Quiere probar un cepillo de dientes Sonicare sin gastar mucho dinero en uno de sus modelos favoritos de gama alta? Puede comprar un kit de la Serie 2 o Serie 3 por tan solo $ 30 hoy en Amazon. Haga clic aquí para ver la lista completa de modelos elegibles y tenga en cuenta que se descontarán $ 10 adicionales en su carrito.
Tapas elásticas de silicona de Tomorrow's Kitchen, paquete de 12 | $14 | Amazonas | Código promocional 20OFFKINJALids son básicamente los calcetines de la cocina; siempre perdiéndose, dejando contenedores huérfanos que nunca podrán volver a cerrarse. Pero, ¿y si sus tapas pudieran estirarse y adaptarse a todos los recipientes, ollas, sartenes e incluso frutas en rodajas grandes que sobran? Nunca más tendrás que preocuparte por perder esa tapa tan específica.
El equipo está a la espera de las medallas que ganó en los Juegos Olímpicos de Invierno de 2022 en Beijing, ya que se está resolviendo un caso de dopaje que involucra a la patinadora artística rusa Kamila Valieva.
Miles de compradores de Amazon recomiendan la funda de almohada de seda Mulberry, y está a la venta en este momento. La funda de almohada de seda viene en varios colores y ayuda a mantener el cabello suave y la piel clara. Compre las fundas de almohada de seda mientras tienen hasta un 46 por ciento de descuento en Amazon
El jueves se presentó una denuncia de delito menor amenazante agravado contra Joe Mixon.
El Departamento de Policía de Lafayette comenzó a investigar a un profesor de la Universidad de Purdue en diciembre después de recibir varias denuncias de un "hombre sospechoso que se acercaba a una mujer".
Al igual que el mundo que nos rodea, el lenguaje siempre está cambiando. Mientras que en eras anteriores los cambios en el idioma ocurrían durante años o incluso décadas, ahora pueden ocurrir en cuestión de días o incluso horas.
Estoy de vuelta por primera vez en seis años. No puedo decirte cuánto tiempo he estado esperando esto.
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
Creo, un poco tarde en la vida, en dar oportunidades a la gente. Generosamente.