¿Cómo navegar mediante programación usando React Router?
Con react-router
puedo usar el Link
elemento para crear enlaces que son manejados de forma nativa por el enrutador de reacción.
Veo que internamente llama this.context.transitionTo(...)
.
Quiero hacer una navegación. No desde un enlace, sino desde una selección desplegable (como ejemplo). ¿Cómo puedo hacer esto en código? Qué es this.context
?
Vi el Navigation
mixin, pero ¿puedo hacer esto sin mixins
?
ACTUALIZACIÓN: 2022: React Router v6.6.1 con useNavigate
El useHistory()
gancho ahora está en desuso. Si está utilizando React Router 6, la forma correcta de navegar mediante programación es la siguiente:
import { useNavigate } from "react-router-dom";
function HomeButton() {
const navigate = useNavigate();
function handleClick() {
navigate("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
React Router v5.1.0 con ganchos
Hay un nuevo useHistory
enlace en React Router >5.1.0 si está utilizando React >16.8.0 y componentes funcionales.
import { useHistory } from "react-router-dom";
function HomeButton() {
const history = useHistory();
function handleClick() {
history.push("/home");
}
return (
<button type="button" onClick={handleClick}>
Go home
</button>
);
}
Reaccionar enrutador v4
Con la v4 de React Router, hay tres enfoques que puede adoptar para el enrutamiento programático dentro de los componentes.
- Utilice el
withRouter
componente de orden superior. - Usar composición y renderizar
<Route>
- Utilizar el
context
.
React Router es principalmente un contenedor de la history
biblioteca. history
maneja la interacción con el navegador window.history
por usted con su navegador y sus historiales de hash. 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.
Una history
instancia tiene dos métodos para navegar: push
y replace
. Si piensa en el history
como una matriz de ubicaciones visitadas, push
agregará una nueva ubicación a la matriz y replace
reemplazará la ubicación actual en la matriz con la nueva. Normalmente querrás utilizar este push
método cuando estés navegando.
En versiones anteriores de React Router, tenía que crear su propia history
instancia, pero en la versión 4 <BrowserRouter>
, los componentes <HashRouter>
, y <MemoryRouter>
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 estén disponibles a través del contexto, debajo del router
objeto.
1. Utilice el withRouter
componente de orden superior
El withRouter
componente de orden superior inyectará el history
objeto como accesorio del componente. Esto le permite acceder a los métodos push
y replace
sin tener que lidiar con el archivo 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 composición y renderiza<Route>
El <Route>
componente no es sólo para hacer coincidir ubicaciones. Puede representar una ruta sin camino y siempre coincidirá con la ubicación actual . El <Route>
componente pasa los mismos accesorios que withRouter
, por lo que podrá acceder a los history
métodos a través del history
accesorio.
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 debe usar si se siente cómodo trabajando con el modelo de contexto de React (la API de contexto de React es estable a partir de la versión 16).
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 sencillas de implementar, por lo que, para la mayoría de los casos de uso, son las mejores opciones.
React-Router v6+ Respuesta
TL;DR: Puedes usar el nuevo useNavigate
gancho.
import { useNavigate } from "react-router-dom";
function Component() {
let navigate = useNavigate();
// Somewhere in your code, e.g. inside a handler:
navigate("/posts");
}
El useNavigate
gancho devuelve una función que se puede utilizar para la navegación programática.
Ejemplo de la documentación del enrutador de reacción
import { useNavigate } from "react-router-dom";
function SignupForm() {
let navigate = useNavigate();
async function handleSubmit(event) {
event.preventDefault();
await submitForm(event.target);
navigate("../success", { replace: true });
// replace: true will replace the current entry in
// the history stack instead of adding a new one.
}
return <form onSubmit={handleSubmit}>{/* ... */}</form>;
}
React-Router 5.1.0+ Respuesta (usando ganchos y React >16.8)
Puede utilizar el useHistory
enlace en Componentes funcionales y navegar mediante programación:
import { useHistory } from "react-router-dom";
function HomeButton() {
let history = useHistory();
// use history.push('/some/path') here
};
React-Router 4.0.0+ Respuesta
En 4.0 y superiores, utilice el historial como accesorio de su componente.
class Example extends React.Component {
// use `this.props.history.push('/some/path')` here
};
NOTA: this.props.history
no existe en el caso de que su componente no haya sido renderizado por <Route>
. Deberías usar <Route path="..." component={YourComponent}/>
to have this.props.history
en YourComponent
React-Router 3.0.0+ Respuesta
En 3.0 y superiores, utilice el enrutador como accesorio de su componente.
class Example extends React.Component {
// use `this.props.router.push('/some/path')` here
};
React-Router 2.4.0+ Respuesta
En 2.4 y superiores, utilice un componente de orden superior para obtener el enrutador como 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+ Respuesta
Esta versión es compatible con versiones anteriores de 1.x, por lo que no es necesaria una guía de actualización. Simplemente repasar los ejemplos debería ser suficiente.
Dicho esto, si deseas cambiar al nuevo patrón, hay un browserHistory
módulo dentro del enrutador al que puedes acceder con
import { browserHistory } from 'react-router'
Ahora tienes acceso al historial de tu navegador, por lo que puedes hacer cosas como insertar, reemplazar, etc... Como:
browserHistory.push('/some/path')
Lectura adicional: Historias y navegación
Respuesta del enrutador React 1.xx
No entraré en detalles sobre la actualización. Puedes leer sobre eso en la Guía de actualización.
El principal cambio sobre la pregunta aquí es el cambio de Navigation
mixin a History
. Ahora está usando la API del historial del navegador para cambiar la ruta, así que la 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
proviene del proyecto rackt/history . No del propio React-Router.
Si no desea utilizar Mixin por algún motivo (tal vez debido a la clase ES6), puede acceder al historial que obtiene del enrutador desde this.props.history
. Solo será accesible para los componentes renderizados por su Router
. Por lo tanto, si desea utilizarlo en algún componente secundario, debe transmitirlo 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í hay una página de ayuda específicamente sobre cómo navegar fuera de su componente.
Recomienda tomar una referencia history = createHistory()
y recurrir replaceState
a ella.
React-Router 0.13.x Respuesta
Me metí en el mismo problema y solo pude encontrar la solución con el mixin de navegación que viene con reaccionar-router.
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 necesidad de acceder.context
O podrías probar el elegante ES6class
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
};
Reaccionar-Router-Redux
Note: if you're using Redux, there is another project called React-Router-Redux that gives you redux bindings for ReactRouter, using somewhat the same approach that React-Redux does
React-Router-Redux has a few methods available that allow for simple navigating from inside action creators. These can be particularly useful for people that have existing architecture in React Native, and they wish to utilize the same patterns in React Web with minimal boilerplate overhead.
Explore the following methods:
push(location)
replace(location)
go(number)
goBack()
goForward()
Here is an example usage, with 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>