Acabo de reemplazar react-router
de v3 a v4.
Pero no estoy seguro de cómo navegar mediante programación en la función miembro de a Component
. es decir, en la handleClick()
función que quiero navegar /path/some/where
después de procesar algunos datos. Solía hacer eso por:
import { browserHistory } from 'react-router'
browserHistory.push('/path/some/where')
Pero no puedo encontrar tales interfaces en v4.
¿Cómo puedo navegar usando v4?
reactjs
ecmascript-6
react-router-v4
Colin Witkamp
fuente
fuente
Component
? Por ejemplo, dentro de las acciones redux.Respuestas:
Si se dirige a entornos de navegador, debe usar el
react-router-dom
paquete, en lugar dereact-router
. Están siguiendo el mismo enfoque que React, para separar el núcleo, (react
) y el código específico de la plataforma, (react-dom
,react-native
) con la sutil diferencia de que no necesita instalar dos paquetes separados, por lo que los paquetes de entorno contienen todo necesitas. Puedes agregarlo a tu proyecto como:yarn add react-router-dom
o
npm i react-router-dom
Lo primero que debe hacer es proporcionar un
<BrowserRouter>
como el componente principal más alto en su aplicación.<BrowserRouter>
usa lahistory
API HTML5 y la administra por usted, por lo que no tiene que preocuparse por instanciarlo usted mismo y pasarlo al<BrowserRouter>
componente como accesorio (como lo hizo en versiones anteriores).En V4, para navegar programáticamente, necesita acceder al
history
objeto, que está disponible a través de Reactcontext
, siempre que tenga un componente de<BrowserRouter>
proveedor como el principal superior en su aplicación. La biblioteca expone a través del contexto elrouter
objeto, que en sí mismo contienehistory
como una propiedad. Lahistory
interfaz ofrece varios métodos de navegación, comopush
,replace
ygoBack
, entre otros. Puede consultar la lista completa de propiedades y métodos aquí .Nota importante para los usuarios de Redux / Mobx
Si está utilizando redux o mobx como su biblioteca de administración de estado en su aplicación, es posible que haya encontrado problemas con los componentes que deberían tener en cuenta la ubicación pero que no se vuelven a reproducir después de activar una actualización de URLEso sucede porque
react-router
pasalocation
a los componentes utilizando el modelo de contexto.Los 2 enfoques para resolver esto son:
<Route />
. Ellocation
objeto actual es uno de los accesorios que un<Route>
pasa al componente que representawithRouter
componente de orden superior, que de hecho tiene el mismo efecto e inyectalocation
como accesorioDejando eso de lado, hay cuatro formas de navegar programáticamente, ordenadas por recomendación:
1.- Usando un
Promueve un estilo declarativo. Antes de v4, los<Route>
componente<Route />
componentes se colocaban en la parte superior de la jerarquía de componentes, teniendo que pensar de antemano en la estructura de sus rutas. Sin embargo, ahora puede tener<Route>
componentes en cualquier parte de su árbol, lo que le permite tener un control más preciso para la representación condicional dependiendo de la URL.Route
inyectamatch
,location
yhistory
como accesorios en su componente. Los métodos de navegación (tales comopush
,replace
,goBack
...) están disponibles como propiedades delhistory
objeto.Hay 3 formas de renderizar algo con a
Route
, usando cualquiera de los doscomponent
,render
ochildren
accesorios, pero no use más de uno en el mismoRoute
. La elección depende del caso de uso, pero básicamente las dos primeras opciones solo mostrarán su componente sipath
coincide con la ubicación de la URL, mientras que conchildren
el componente se mostrará si la ruta coincide con la ubicación o no (útil para ajustar la interfaz de usuario basada en la URL pareo).Si desea personalizar la salida de representación de componente , es necesario envolver su componente en una función y utiliza la
render
opción, a fin de pasar a su componente cualesquiera otros apoyos que usted desea, además dematch
,location
yhistory
. Un ejemplo para ilustrar:2.- Usando
withRouter
HoCEste componente de orden superior inyectará los mismos accesorios que
Route
. Sin embargo, conlleva la limitación de que solo puede tener 1 HoC por archivo.3.- Usando un
La representación de aRedirect
componente<Redirect>
navegará a una nueva ubicación. Pero tenga en cuenta que, de forma predeterminada , la ubicación actual se reemplaza por la nueva, como las redirecciones del lado del servidor (HTTP 3xx). La nueva ubicación es proporcionada porto
prop, que puede ser una cadena (URL para redirigir a) o unlocation
objeto. Si quieres insertar una nueva entrada en el historial , pasa también unpush
accesorio y configúralo entrue
4.- Accediendo
Un poco desanimado porque el contexto sigue siendo una API experimental y es probable que se rompa / cambie en futuras versiones de Reactrouter
manualmente a través del contextoNo hace falta decir que también hay otros componentes del enrutador destinados a ecosistemas que no son del navegador, como el
<NativeRouter>
que replica una pila de navegación en la memoria y apunta a la plataforma React Native, disponible a través delreact-router-native
paquete.Para cualquier referencia adicional, no dude en consultar los documentos oficiales . También hay un video hecho por uno de los coautores de la biblioteca que proporciona una introducción bastante buena al react-router v4, destacando algunos de los principales cambios.
fuente
withRouter
dereact-router-dom
withRouter
dereact-router-dom
. El history.push cambia la url, pero no parece cargar<Route>
hasta que<Router>
dentro un componente React con el que está decorado@observer
, lo que desencadena este problema . La solución es tener@withRouter
en cada componente de React.withRouter
es simplemente un HOC que utiliza unRoute
bajo el capó. Lo que significa que solo usa 3 accesorios, historia, partido y ubicación . En el ejemplo anterior, parece quepush
es un accesorio quewithRouter
se agregaríaButtonToNavigate
, pero ese no es el caso.props.history.push
tendría que ser utilizado en su lugar. Espero que esto ayude a otros que estaban un poco confundidos.browserHistory.push('/path/some/where')
simplemente parece mucho más simple. Los autores están tratando de desalentar la programación imperativa, ¡pero a veces simplemente funciona mejor!La forma más fácil de hacerlo:
this.props.history.push("/new/url")
Nota:
history
prop
del componente primario al componente en el que desea invocar la acción si no está disponible.fuente
this.props.history
disponible en su componente, puedeimport {withRouter} from 'react-router-dom'
y luegoexport default withRouter(MyComponent)
(oconst MyComponent = withRouter(...)
) e insertará elhistory
elemento en los accesorios de su componente.history.push
y simplemente activar la actualización como cuando hacemos clic en<Link>
Tuve un problema similar al migrar a React-Router v4, así que intentaré explicar mi solución a continuación.
No considere esta respuesta como la forma correcta de resolver el problema, imagino que hay una buena posibilidad de que surja algo mejor a medida que React Router v4 se vuelva más maduro y deje beta (incluso puede existir y simplemente no lo descubrí) .
Por contexto, tuve este problema porque ocasionalmente uso
Redux-Saga
para cambiar programáticamente el objeto de historial (por ejemplo, cuando un usuario se autentica con éxito).En los documentos de React Router, eche un vistazo al
<Router>
componente y verá que tiene la capacidad de pasar su propio objeto de historia a través de un accesorio. Esta es la esencia de la solución - que la oferta del objeto historia aReact-Router
partir de un mundial módulo.Pasos:
yarn add history
onpm install history --save
crear un archivo llamado
history.js
en suApp.js
carpeta de nivel (esta era mi preferencia)Agregue este objeto de historial a su componente de enrutador de esta manera
Ajuste la URL como antes importando su objeto de historial global:
Todo debería estar sincronizado ahora, y también tiene acceso a una forma de configurar el objeto de historial mediante programación y no a través de un componente / contenedor.
fuente
Route
componente.TL; DR:
La respuesta simple y declarativa es que debe usar
<Redirect to={URL} push={boolean} />
en combinación consetState()
Ejemplo completo aquí . Lee más aquí .
PD. El ejemplo utiliza los inicializadores de propiedades ES7 + para inicializar el estado. Mira aquí también, si estás interesado.
fuente
history.push()
métodos.Use
useHistory
hook si está usando componentes de funciónPuede usar
useHistory
hook para obtenerhistory
instancia.El
useHistory
gancho le da acceso a la instancia de historial que puede usar para navegar.Usar
history
propiedad dentro de los componentes de la páginaReact Router inyecta algunas propiedades, incluidos los
history
componentes de la página.Envuelva los componentes secundarios
withRouter
para inyectar las propiedades del enrutadorwithRouter
wrapper inyecta las propiedades del enrutador a los componentes. Por ejemplo, puede usar este contenedor para inyectar el enrutador para cerrar el componente del botón ubicado dentro del menú del usuario.fuente
También puede simplemente usar accesorios para acceder al objeto de historial:
this.props.history.push('new_url')
fuente
this.props.history
disponible en su componente, puedeimport {withRouter} from 'react-router-dom'
y luegoexport default withRouter(MyComponent)
(oconst MyComponent = withRouter(...)
) e insertará elhistory
elemento en los accesorios de su componente.Paso 1: solo hay una cosa para importar:
Paso 2: en tu ruta, pasa el historial:
Paso 3: el historial se acepta como parte de los accesorios en el siguiente Componente, por lo que puede simplemente:
Eso fue fácil y realmente poderoso.
fuente
Esto funciona:
fuente
Mi respuesta es similar a la de Alex . No estoy seguro de por qué React-Router hizo esto tan innecesariamente complicado. ¿Por qué debería tener que envolver mi componente con un HoC solo para obtener acceso a lo que es esencialmente global?
De todos modos, si echas un vistazo a cómo se implementaron
<BrowserRouter>
, es solo una pequeña envoltura alrededor de la historia .Podemos extraer ese historial para poder importarlo desde cualquier lugar. Sin embargo, el truco es que si está haciendo renderizado del lado del servidor e intenta con
import
el módulo de historial, no funcionará porque usa API solo para el navegador. Pero eso está bien porque generalmente solo redirigimos en respuesta a un clic o algún otro evento del lado del cliente. Por lo tanto, probablemente esté bien simularlo:Con la ayuda de webpack, podemos definir algunos variables para saber en qué entorno estamos:
Y ahora puedes
De donde sea. Simplemente devolverá un módulo vacío en el servidor.
Si no desea utilizar estos vars mágicos, solo tendrá que hacerlo
require
en el objeto global donde sea necesario (dentro de su controlador de eventos).import
no funcionará porque solo funciona en el nivel superior.fuente
Creo que @rgommezz cubre la mayoría de los casos menos uno que creo que es bastante importante.
Esto me permite escribir un servicio simple con acciones / llamadas a las que puedo llamar para hacer la navegación desde cualquier componente que desee sin hacer mucho HoC en mis componentes ...
No está claro por qué nadie ha proporcionado esta solución antes. Espero que ayude, y si ve algún problema con esto, hágamelo saber.
fuente
He estado probando v4 durante unos días y ... ¡hasta ahora me encanta! Simplemente tiene sentido después de un tiempo.
También tenía la misma pregunta y encontré que manejarlo como el siguiente funcionó mejor (y podría ser incluso cómo se pretende). Utiliza estado, un operador ternario y
<Redirect>
.En el constructor ()
En el render ()
En el clickhandler ()
Espero eso ayude. Házmelo saber.
fuente
Luché con esto por un tiempo, algo tan simple, pero tan complicado, porque ReactJS es una forma completamente diferente de escribir aplicaciones web, ¡es muy extraño para nosotros, las personas mayores!
Creé un componente separado para abstraer el desastre:
Luego agréguelo a su
render()
método:fuente
Como no hay otra forma de lidiar con este diseño horrible, escribí un componente genérico que utiliza el enfoque
withRouter
HOC . El siguiente ejemplo es envolver unbutton
elemento, pero puede cambiar a cualquier elemento en el que pueda hacer clic:Uso:
fuente
Si no ha encontrado this.props.history disponible en su componente, intente esto
fuente
Como a veces prefiero cambiar las rutas por aplicación y luego por botones, este es un ejemplo de trabajo mínimo que funciona para mí:
fuente
Para aquellos de ustedes que requieren redirigir antes de iniciar completamente un enrutador usando
React Router
oReact Router Dom
puede proporcionar una redirección simplemente accediendo al objeto de historial y presionando un nuevo estado dentro de su construcciónapp.js
. Considera lo siguiente:Aquí queremos cambiar las Rutas de salida que dependen de un subdominio, al interactuar con el objeto de historial antes de que el componente se procese, podemos redirigir efectivamente sin dejar nuestras rutas intactas.
fuente