react example ejemplo change reactjs react-router browser-history

reactjs - example - ¿Cómo paso el estado a través de React_router?



react router dom redux (2)

No puede cambiar el estado del enrutador React una vez que se haya montado el componente del enrutador. Puede escribir su propio componente de ruta HTML5 y escuchar los cambios de URL.

class MyRouter extend React.component { constructor(props,context){ super(props,context); this._registerHashEvent = this._registerHashEvent.bind(this) } _registerHashEvent() { window.addEventListener("hashchange", this._hashHandler.bind(this), false); } ... ... render(){ return ( <div> <RouteComponent /> </div>) }

Aquí está el archivo que me está causando problemas:

var Routers = React.createClass({ getInitialState: function(){ return{ userName: "", relatives: [] } }, userLoggedIn: function(userName, relatives){ this.setState({ userName: userName, relatives: relatives, }) }, render: function() { return ( <Router history={browserHistory}> <Route path="/" userLoggedIn={this.userLoggedIn} component={LogIn}/> <Route path="feed" relatives={this.state.relatives} userName={this.state.userName} component={Feed}/> </Router> ); } });

Estoy tratando de pasar el nuevo this.state.relatives y this.state.userName través de las rutas a mi componente "feed". Pero estoy recibiendo este mensaje de error:

Advertencia: [react-router] No puedes cambiar; será ignorado

Sé por qué sucede esto, pero no sé de qué otra forma debo pasar los estados a mi componente "feed". ¡He estado intentando solucionar este problema durante las últimas 5 horas y me estoy volviendo bastante desesperado!

¡Por favor ayuda! Gracias

SOLUCIÓN:

Las respuestas a continuación fueron útiles y agradezco a los atletas, pero no fueron la forma más fácil de hacerlo. La mejor manera de hacerlo en mi caso resultó ser esta: cuando cambias de ruta, simplemente le adjuntas un mensaje así:

browserHistory.push({pathname: ''/pathname'', state: {message: "hello, im a passed message!"}});

O si lo haces a través de un enlace:

<Link to={{ pathname: ''/pathname'', state: { message: ''hello, im a passed message!'' } }}/>

fuente: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/docs/api/location.md

En el componente que está intentando alcanzar, puede acceder a la variable como esta, por ejemplo:

componentDidMount: function() { var recievedMessage = this.props.location.state.message },

¡Espero que esto ayude! :)


tl; dr lo mejor que puede hacer es usar una tienda como redux o mobx cuando administre el estado que debe ser accesible a través de su aplicación. Esas bibliotecas permiten que sus componentes se conecten / observen el estado y se mantengan actualizados de cualquier cambio de estado.

¿Qué es una <Route> ?

La razón por la que no puede pasar props a través de componentes <Route> es que no son componentes reales en el sentido de que no representan nada. En su lugar, se utilizan para construir un objeto de configuración de ruta.

Eso significa que esto:

<Router history={browserHistory}> <Route path=''/'' component={App}> <Route path=''foo'' component={Foo} /> </Route> </Router>

es equivalente a esto:

<Router history={browserHistory} routes={{ path: ''/'', component: App, childRoutes: [ { path: ''foo'', component: Foo } ] }} />

Las rutas solo se evalúan en el montaje inicial, por lo que no puede pasarles nuevos accesorios.

Apoyos estáticos

Si tiene algunos accesorios estáticos que desea pasar a su tienda, puede crear su propio componente de orden superior que los inyectará en la tienda. Desafortunadamente, esto solo funciona para apoyos estáticos porque, como se indicó anteriormente, los <Route> solo se evalúan una vez.

function withProps(Component, props) { return function(matchProps) { return <Component {...props} {...matchProps} /> } } class MyApp extends React.Component { render() { return ( <Router history={browserHistory}> <Route path=''/'' component={App}> <Route path=''foo'' component={withProps(Foo, { test: ''ing'' })} /> </Route> </Router> ) } }

Usando location.state

location.state es una forma conveniente de pasar el estado entre los componentes cuando estás navegando. Sin embargo, tiene un inconveniente importante, que es que el estado solo existe cuando se navega dentro de su aplicación. Si un usuario sigue un enlace a su sitio web, no habrá ningún estado adjunto a la ubicación.

Usando una tienda

Entonces, ¿cómo pasar los datos a los component su ruta? Una forma común es utilizar una tienda como redux o mobx . Con redux , puede connect su componente a la tienda utilizando un componente de orden superior. Luego, cuando el component su ruta (que es realmente el HOC con el componente de su ruta como su hijo) se procesa, puede obtener información actualizada de la tienda.

const Foo = (props) => ( <div>{props.username}</div> ) function mapStateToProps(state) { return { value: state.username }; } export default connect(mapStateToProps)(Foo)

No estoy particularmente familiarizado con mobx , pero a mi entender, puede ser incluso más fácil de configurar. El uso de redux , mobx o uno de los otros estados es una excelente manera de pasar el estado a través de su aplicación.

Nota: Puedes dejar de leer aquí. A continuación se muestran ejemplos plausibles para pasar el estado, pero probablemente debería usar una biblioteca de tienda.

Sin una tienda

¿Qué pasa si no quieres usar una tienda? ¿Estás fuera de suerte? No, pero tienes que usar una característica experimental de React: el context . Para utilizar el context , uno de sus componentes principales debe definir explícitamente un método getChildContext así como un objeto childContextTypes . Cualquier componente secundario que quiera acceder a estos valores a través del context deberá definir un objeto propTypes (similar a propTypes ).

class MyApp extends React.Component { getChildContext() { return { username: this.state.username } } } MyApp.childContextTypes = { username: React.PropTypes.object } const Foo = (props, context) => ( <div>{context.username}</div> ) Foo.contextTypes = { username: React.PropTypes.object }

Incluso puede escribir su propio componente de orden superior que inyecta automáticamente los valores de context como props de sus component <Route> . Esto sería algo así como una "tienda de hombres pobres". Podría hacerlo funcionar, pero lo más probable es que sea menos eficiente y con más errores que el uso de una de las bibliotecas de tiendas mencionadas anteriormente.

¿Qué pasa con React.cloneElement ?

Hay otra forma de proporcionar accesorios a un component <Route> , pero solo funciona de un nivel a la vez. Esencialmente, cuando React Router está procesando componentes basados ​​en la ruta actual, primero crea un elemento para el <Route> más emparejado más anidado. Luego pasa ese elemento como elemento secundario secundario al crear un elemento para el siguiente <Route> acceso más profundamente anidado. Eso significa que en el método de render del segundo componente, puede usar React.cloneElement para clonar el elemento React.cloneElement existente y agregarle elementos adicionales.

const Bar = (props) => ( <div>These are my props: {JSON.stringify(props)}</div> ) const Foo = (props) => ( <div> This is my child: { props.children && React.cloneElement(props.children, { username: props.username }) } </div> )

Por supuesto, esto es tedioso, especialmente si tuviera que pasar esta información a través de múltiples niveles de component de <Route> . También necesitaría administrar su estado dentro de su componente <Route> (es decir, <Route path=''/'' component={Base}> ) porque no tendría una forma de inyectar el estado desde los componentes principales del <Router> .