Pregunta Navegue mediante programación usando el enrutador de reacción


Con react-router Puedo usar el Link elemento para crear enlaces que son manejados de forma nativa por el enrutador de reacción.

Veo internamente llamadas this.context.transitionTo(...).

Quiero hacer una navegación, pero no desde un enlace, de una selección desplegable, por ejemplo. ¿Cómo puedo hacer esto en el código? Que es this.context?

yo vi el Navigation mixin, pero ¿puedo hacer esto sin mixins?


775
2018-06-26 17:38


origen


Respuestas:


React Router v4

Con v4 de React Router, hay tres enfoques que puede tomar para el enrutamiento programático dentro de los componentes.

  1. Utilizar el withRouter componente de orden superior.
  2. Usa la composición y renderiza <Route>
  3. Utilizar el context.

React Router es principalmente un envoltorio alrededor del history biblioteca. history maneja la interacción con el navegador window.history para ti con su navegador y hash historys. También proporciona un historial de memoria que es útil para entornos que no tienen un historial global. Esto es particularmente útil en el desarrollo de aplicaciones móviles (react-native) y pruebas unitarias con Node.

UN history instancia tiene dos métodos para navegar: push y replace. Si piensas en el history como una variedad de lugares visitados, push agregará una nueva ubicación a la matriz y replace reemplazará la ubicación actual en la matriz con la nueva. Por lo general, querrás usar push método cuando estás navegando

En versiones anteriores de React Router, tenías que crear tu propio history ejemplo, pero en v4 el <BrowserRouter>, <HashRouter>y <MemoryRouter> componentes crearán instancias de navegador, hash y memoria para usted. React Router hace que las propiedades y métodos de la history instancia asociada con su enrutador disponible a través del contexto, debajo del router objeto.

1. Usa el withRouter componente de orden superior

los withRouter componente de orden superior inyectará el history objeto como un apoyo del componente. Esto le permite acceder al push y replace métodos sin tener que lidiar con el context.

import { withRouter } from 'react-router-dom'
// this also works with react-router-native

const Button = withRouter(({ history }) => (
  <button
    type='button'
    onClick={() => { history.push('/new-location') }}
  >
    Click Me!
  </button>
))

2. Usa la composición y renderiza <Route>

los <Route> componente no es solo para ubicaciones coincidentes. Puede renderizar una ruta sin ruta y siempre coincidirá con la ubicación actual. los <Route> componente pasa los mismos apoyos que withRouter, entonces podrás acceder al history métodos a través de history apuntalar.

import { Route } from 'react-router-dom'

const Button = () => (
  <Route render={({ history}) => (
    <button
      type='button'
      onClick={() => { history.push('/new-location') }}
    >
      Click Me!
    </button>
  )} />
)

3. Usa el contexto *

* Pero probablemente no deberías

La última opción es una que solo debes usar si te sientes cómodo trabajando con React contexto modelo. Aunque el contexto es una opción, se debe destacar que el contexto es una API inestable y React tiene una sección Por qué no usar el contexto en su documentación. ¡Así que utilícelo bajo su propio riesgo!

const Button = (props, context) => (
  <button
    type='button'
    onClick={() => {
      // context.history.push === history.push
      context.history.push('/new-location')
    }}
  >
    Click Me!
  </button>
)

// you need to specify the context type so that it
// is available within the component
Button.contextTypes = {
  history: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  })
}

1 y 2 son las opciones más simples para implementar, por lo que para la mayoría de los casos de uso son sus mejores apuestas.


614
2018-02-08 18:39



React-Router 4.0.0+ Responder

En la versión 4.0 y superior, usa el historial como un elemento de tu componente.

class Example extends React.Component {
   // use `this.props.history.push('/some/path')` here
};

React-Router 3.0.0+ Responder

En 3.0 y superior, use el enrutador como un accesorio de su componente.

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

React-Router 2.4.0+ Responder

En 2.4 y superior, use un componente de orden superior para que el enrutador sea un accesorio de su componente.

import { withRouter } from 'react-router';

class Example extends React.Component {
   // use `this.props.router.push('/some/path')` here
};

// Export the decorated class
var DecoratedExample = withRouter(Example);

// PropTypes
Example.propTypes = {
  router: React.PropTypes.shape({
    push: React.PropTypes.func.isRequired
  }).isRequired
};

React-Router 2.0.0+ Responder

Esta versión es retrocompatible con 1.x, por lo que no es necesario tener una Guía de actualización. Simplemente revisar los ejemplos debería ser lo suficientemente bueno.

Dicho esto, si desea cambiar al nuevo patrón, hay un módulo browserHistory dentro del enrutador al que puede acceder con

import { browserHistory } from 'react-router'

Ahora tiene acceso al historial de su navegador, por lo que puede hacer cosas como presionar, reemplazar, etc ... Me gusta:

browserHistory.push('/some/path')

Otras lecturas: Historias y Navegación


React-Router 1.x.x Responder

No entraré en la actualización de detalles. Puedes leer sobre eso en el Guía de actualización

El principal cambio sobre la pregunta aquí es el cambio de Navigation mixin a History. Ahora está usando el historial del navegadorAPI para cambiar la ruta, así que usaremos pushState() de ahora en adelante.

Aquí hay un ejemplo usando Mixin:

var Example = React.createClass({
  mixins: [ History ],
  navigateToHelpPage () {
    this.history.pushState(null, `/help`);
  }
})

Tenga en cuenta que esto History viene de rackt / historia proyecto. No de React-Router en sí.

Si no quiere usar Mixin por alguna razón (tal vez debido a la clase ES6), entonces puede acceder al historial que obtiene del enrutador desde this.props.history. Solo será accesible para los componentes presentados por su Enrutador. Por lo tanto, si desea usarlo en cualquier componente secundario, debe pasarlo como un atributo a través de props.

Puede leer más sobre la nueva versión en su Documentación 1.0.x

Aquí está una página de ayuda específicamente sobre cómo navegar fuera de su componente

Recomienda agarrar una referencia history = createHistory() y llamando replaceState en ese.

React-Router 0.13.x Responder

Me metí en el mismo problema y solo pude encontrar la solución con la combinación de navegación que viene con el router de reacción.

Así es como lo hice

import React from 'react';
import {Navigation} from 'react-router';

let Authentication = React.createClass({
  mixins: [Navigation],

  handleClick(e) {
    e.preventDefault();

    this.transitionTo('/');
  },

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

Pude llamar transitionTo() sin la necesidad de acceder .context

O podrías probar el elegante ES6 class

import React from 'react';

export default class Authentication extends React.Component {
  constructor(props) {
    super(props);
    this.handleClick = this.handleClick.bind(this);
  }

  handleClick(e) {
    e.preventDefault();

    this.context.router.transitionTo('/');
  }

  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
}

Authentication.contextTypes = {
  router: React.PropTypes.func.isRequired
};

React-Router-Redux

Nota: si está usando Redux, hay otro proyecto llamado    React-Router-Redux eso te da   enlaces reductores para ReactRouter, utilizando de alguna manera el mismo enfoque que    React-Redux hace

React-Router-Redux tiene algunos métodos disponibles que permiten navegar desde dentro de los creadores de acciones. Estos pueden ser particularmente útiles para las personas que tienen una arquitectura existente en React Native, y desean utilizar los mismos patrones en React Web con una sobrecarga estándar mínima.

Explore los siguientes métodos:

  • push(location)
  • replace(location)
  • go(number)
  • goBack()
  • goForward()

Aquí hay un ejemplo de uso, con Redux-Thunk:

./actioncreators.js

import { goBack } from 'react-router-redux'

export const onBackPress = () => (dispatch) => dispatch(goBack())

./viewcomponent.js

<button
  disabled={submitting}
  className="cancel_button"
  onClick={(e) => {
    e.preventDefault()
    this.props.onBackPress()
  }}
>
  CANCEL
</button>

662
2018-06-26 17:49



React-Router v2

Para la versión más reciente (v2.0.0-rc5), el método de navegación recomendado es presionar directamente en el singleton de historia. Puedes ver eso en acción en el Navegando fuera del documento de Componentes.

Extracto relevante:

import { browserHistory } from 'react-router';
browserHistory.push('/some/path');

Si usa la API de enrutador de reacción más nueva, debe hacer uso del historyde this.props cuando dentro de componentes así:

this.props.history.push('/some/path');

También ofrece pushState pero eso está en desuso por cada advertencia registrada.

Si usas react-router-redux, ofrece una push función que puede despachar así:

import { push } from 'react-router-redux';
this.props.dispatch(push('/some/path'));

Sin embargo, esto solo se puede usar para cambiar la URL, no para navegar realmente a la página.


466
2018-01-18 20:32



Así es como haces esto con react-router v2.0.0 con ES6. react-router se ha alejado de mixins.

import React from 'react';

export default class MyComponent extends React.Component {
  navigateToPage = () => {
    this.context.router.push('/my-route')
  };

  render() {
    return (
      <button onClick={this.navigateToPage}>Go!</button>
    );
  }
}

MyComponent.contextTypes = {
  router: React.PropTypes.object.isRequired
}

34
2018-01-22 20:46



Para este, que no controla el lado del servidor y debido a esto está utilizando el enrutador hash v2:

Coloque su historia en un archivo separado (por ejemplo, app_history.js ES6):

import { useRouterHistory } from 'react-router'
import { createHashHistory } from 'history'
const appHistory = useRouterHistory(createHashHistory)({ queryKey: false });

export default appHistory;

¡Y úsalo en todas partes!

Su punto de entrada para reaccionar-enrutador (app.js ES6):

import React from 'react'
import { render } from 'react-dom'
import { Router, Route, Redirect } from 'react-router'
import appHistory from './app_history'
...
const render((
  <Router history={appHistory}>
  ...
  </Router>
), document.querySelector('[data-role="app"]'));

Su navegación dentro de cualquier componente (ES6):

import appHistory from '../app_history'
...
ajaxLogin('/login', (err, data) => {
  if (err) {
    console.error(err); // login failed
  } else {
    // logged in
    appHistory.replace('/dashboard'); // or .push() if you don't need .replace()
  }
})

25
2018-03-19 12:59



React-Router 4.x Respuesta:

Por mi parte, me gusta tener un solo objeto de historial que pueda llevar incluso fuera de los componentes. Lo que me gusta hacer es tener un único archivo history.js que importo a pedido, y simplemente manipularlo.

Solo tienes que cambiar BrowserRouter al Enrutador, y especifique el apoyo de la historia. Esto no cambia nada para ti, excepto que tienes tu propio objeto de historial que puedes manipular como quieras.

Necesitas instalar historia, la biblioteca utilizada por react-router.

Ejemplo de uso, notación ES6:

history.js

import createBrowserHistory from 'history/createBrowserHistory'
export default createBrowserHistory()

BasicComponent.js

import React, { Component } from 'react';
import history from './history';

class BasicComponent extends Component {

    goToIndex(e){
        e.preventDefault();
        history.push('/');
    }

    render(){
        return <a href="#" onClick={this.goToIndex}>Previous</a>;
    }
}

EDITAR 16 de abril de 2018:

Si tiene que navegar desde un componente que realmente se representa desde un Route componente, también puede acceder al historial desde los accesorios, así:

BasicComponent.js

import React, { Component } from 'react';

class BasicComponent extends Component {

    navigate(e){
        e.preventDefault();
        this.props.history.push('/url');
    }

    render(){
        return <a href="#" onClick={this.navigate}>Previous</a>;
    }
}

20
2018-06-06 22:14



Advertencia: esta respuesta solo cubre las versiones de ReactRouter anteriores a la 1.0

¡Actualizaré esta respuesta con casos de uso 1.0.0-rc1 después!

Puedes hacer esto sin mixins también.

let Authentication = React.createClass({
  contextTypes: {
    router: React.PropTypes.func
  },
  handleClick(e) {
    e.preventDefault();
    this.context.router.transitionTo('/');
  },
  render(){
    return (<div onClick={this.handleClick}>Click me!</div>);
  }
});

El problema con los contextos es que no es accesible a menos que defina el contextTypes en la clase

En cuanto a lo que es contexto, es un objeto, como accesorios, que se transmite de padres a hijos, pero se transmite implícitamente, sin tener que redeclarar accesorios cada vez. Ver https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html


19
2018-06-30 06:14