alan souza
Tengo un componente que recibe a través de props un <Link/>
objeto de enrutador de reacción. Cada vez que el usuario hace clic en el botón ‘siguiente’ dentro de este componente, quiero invocar <Link/>
objeto manualmente.
En este momento, estoy usando árbitros para acceder a la instancia de respaldo y haciendo clic manualmente en la etiqueta ‘a’ que <Link/>
genera
Pregunta: ¿Hay alguna manera de invocar manualmente el enlace (por ejemplo, this.props.next.go
)?
Este es el código actual que tengo:
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />
//in Document.js
...
var Document = React.createClass({
_onClickNext: function() {
var next = this.refs.next.getDOMNode();
next.querySelectorAll('a').item(0).click(); //this sounds like hack to me
},
render: function() {
return (
...
<div ref="next">{this.props.next} <img src="rightArrow.png" onClick={this._onClickNext}/></div>
...
);
}
});
...
Este es el código que me gustaría tener:
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
<Document next={sampleLink} />
//in Document.js
...
var Document = React.createClass({
render: function() {
return (
...
<div onClick={this.props.next.go}>{this.props.next.label} <img src="rightArrow.png" /> </div>
...
);
}
});
...
mate lo
React Router v6 – React 17+ (actualizado el 14/01/2022)
import React, {useCallback} from 'react';
import {useNavigate} from 'react-router-dom';
export default function StackOverflowExample() {
const navigate = useNavigate();
const handleOnClick = useCallback(() => navigate('/sample', {replace: true}), [navigate]);
return (
<button type="button" onClick={handleOnClick}>
Go home
</button>
);
}
Nota: Para esta respuesta, el cambio principal entre v6 y v5 es useNavigate
es ahora el gancho React preferido. useHistory
está en desuso y no se recomienda.
React Router v5 – React 16.8+ con ganchos
Si estás aprovechando Ganchos de reacciónpuedes aprovechar las useHistory
API que proviene de React Router v5.
import React, {useCallback} from 'react';
import {useHistory} from 'react-router-dom';
export default function StackOverflowExample() {
const history = useHistory();
const handleOnClick = useCallback(() => history.push('/sample'), [history]);
return (
<button type="button" onClick={handleOnClick}>
Go home
</button>
);
}
Otra forma de escribir el controlador de clics si no desea utilizar useCallback
const handleOnClick = () => history.push('/sample');
React Router v4 – Componente de redirección
La forma recomendada de v4 es permitir que su método de procesamiento atrape una redirección. Utilice el estado o los accesorios para determinar si es necesario mostrar el componente de redirección (lo que luego activará una redirección).
import { Redirect } from 'react-router';
// ... your class implementation
handleOnClick = () => {
// some action...
// then redirect
this.setState({redirect: true});
}
render() {
if (this.state.redirect) {
return <Redirect push to="/sample" />;
}
return <button onClick={this.handleOnClick} type="button">Button</button>;
}
Referencia: https://reacttraining.com/react-router/web/api/Redirect
React Router v4 – Contexto del enrutador de referencia
También puedes aprovechar Router
El contexto que está expuesto al componente React.
static contextTypes = {
router: PropTypes.shape({
history: PropTypes.shape({
push: PropTypes.func.isRequired,
replace: PropTypes.func.isRequired
}).isRequired,
staticContext: PropTypes.object
}).isRequired
};
handleOnClick = () => {
this.context.router.push('/sample');
}
Así es como <Redirect />
funciona bajo el capó.
Referencia: https://github.com/ReactTraining/react-router/blob/master/packages/react-router/modules/Redirect.js#L46,L60
React Router v4 – Objeto de historial de mutación externa
Si aún necesita hacer algo similar a la implementación de v2, puede crear una copia de BrowserRouter
luego exponer el history
como una constante exportable. A continuación se muestra un ejemplo básico, pero puede componerlo para inyectarlo con accesorios personalizables si es necesario. Hay advertencias señaladas con los ciclos de vida, pero siempre debe volver a renderizar el enrutador, al igual que en v2. Esto puede ser útil para los redireccionamientos después de una solicitud de API desde una función de acción.
// browser router file...
import createHistory from 'history/createBrowserHistory';
import { Router } from 'react-router';
export const history = createHistory();
export default class BrowserRouter extends Component {
render() {
return <Router history={history} children={this.props.children} />
}
}
// your main file...
import BrowserRouter from './relative/path/to/BrowserRouter';
import { render } from 'react-dom';
render(
<BrowserRouter>
<App/>
</BrowserRouter>
);
// some file... where you don't have React instance references
import { history } from './relative/path/to/BrowserRouter';
history.push('/sample');
Último BrowserRouter
extender: https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js
Reaccionar enrutador v2
Empuje un nuevo estado a la browserHistory
instancia:
import {browserHistory} from 'react-router';
// ...
browserHistory.push('/sample');
Referencia: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md
-
hashHistory.push(‘/muestra’); si está utilizando hashHistory en lugar de browserHistory
– sanath_p
21 dic 2016 a las 22:40
-
esto es especialmente útil en la biblioteca material-ui ya que usar containerElement={} no siempre invoca el enlace
– Vishal Disawar
28 de enero de 2017 a las 6:07
-
Tenga en cuenta que con la opción de redireccionamiento debe especificar push (es decir,
). De forma predeterminada, realizará un reemplazo que no es lo mismo que invocar manualmente un enlace – aw04
3 mayo 2017 a las 15:28
-
@jokab puede usar
en lugar de github.com/ReactTraining/react-router/blob/master/packages/… – Matt Lo
19 de septiembre de 2017 a las 3:57
-
Redirigir no funciona para mí, pero la solución aw04 con withRouter es más simple y funciona
– stackdave
10 de junio de 2018 a las 5:35
aw04
React Router 4 incluye un con enrutador HOC que le da acceso a la history
objeto a través de this.props
:
import React, {Component} from 'react'
import {withRouter} from 'react-router-dom'
class Foo extends Component {
constructor(props) {
super(props)
this.goHome = this.goHome.bind(this)
}
goHome() {
this.props.history.push("https://stackoverflow.com/")
}
render() {
<div className="foo">
<button onClick={this.goHome} />
</div>
}
}
export default withRouter(Foo)
-
Esto funcionó para mí y parece la solución más simple.
– Rubycut
27 de junio de 2017 a las 12:29
-
Esta es la mejor solución. No entiendo por qué tiene tan pocos votos.
– Benoit
5 de noviembre de 2017 a las 21:50
-
sí, puede hacer clic en el enlace varias veces y la función de retroceso del navegador no funcionará. tendrá que hacer clic en el navegador atrás varias veces para volver realmente
– Vladyslav Tereshin
4 de marzo de 2019 a las 10:42
-
@VladyslavTereshyn puede agregar algo de lógica condicional: if ((this.props.location.pathname + this.props.location.search) !== browserToPath) { … }
– MattWeiler
20 de abril de 2020 a las 14:16
-
después de buscar durante una hora, esta solución finalmente funcionó. ¡Gracias!
– Hombre iónico
17 de agosto de 2021 a las 15:47
paulo mateus
En el versión 5.xpuedes usar useHistory
gancho de react-router-dom
:
// Sample extracted from https://reacttraining.com/react-router/core/api/Hooks/usehistory
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>
);
}
-
Esta es la mejor solución. Si agrega algo de lógica condicional, puede evitar entradas duplicadas en el historial cuando un usuario hace clic en el mismo botón varias veces:
if ((routerHistory.location.pathname + routerHistory.location.search) !== navigateToPath) { routerHistory.push(navigateToPath); }
– MattWeiler
20 de abril de 2020 a las 15:37
-
necesitaba declarar
history
variable, directorio invocandouseHistory().push
no está permitido por las reglas de ganchos– onmyway133
2 jun 2020 a las 16:00
-
esta parece la solución reactiva más moderna.
– Young Jae
30 de julio de 2020 a las 9:50
-
Esto está bien 👌 y fuera de curso funciona para v5.x Con las funciones de flecha, uno podría simplemente avanzar como
onClick={ () => history.push('/home') }
– KeshavDulal
23 de septiembre de 2020 a las 6:37
grechut
o incluso puede intentar ejecutar onClick this (solución más violenta):
window.location.assign("/sample");
Las respuestas aquí están desactualizadas.
Reaccionar enrutador 6
useHistory
está en desuso v6 usa el useNavigate
gancho en su lugar.
import { useNavigate } from 'react-router-dom'
const navigate = useNavigate()
navigate(`/somewhere`, { replace: true })
Ok, creo que pude encontrar una solución adecuada para eso.
Ahora, en lugar de enviar <Link/>
como apuntalar a Documento, envío <NextLink/>
que es un contenedor personalizado para el enlace del enrutador de reacción. Al hacer eso, puedo tener la flecha hacia la derecha como parte de la estructura del enlace y al mismo tiempo evito tener un código de enrutamiento dentro del objeto Documento.
El código actualizado se ve así:
//in NextLink.js
var React = require('react');
var Right = require('./Right');
var NextLink = React.createClass({
propTypes: {
link: React.PropTypes.node.isRequired
},
contextTypes: {
transitionTo: React.PropTypes.func.isRequired
},
_onClickRight: function() {
this.context.transitionTo(this.props.link.props.to);
},
render: function() {
return (
<div>
{this.props.link}
<Right onClick={this._onClickRight} />
</div>
);
}
});
module.exports = NextLink;
...
//in MasterPage.js
var sampleLink = <Link to="/sample">Go To Sample</Link>
var nextLink = <NextLink link={sampleLink} />
<Document next={nextLink} />
//in Document.js
...
var Document = React.createClass({
render: function() {
return (
...
<div>{this.props.next}</div>
...
);
}
});
...
PD: Si está utilizando la última versión de react-router, es posible que deba usar this.context.router.transitionTo
en lugar de this.context.transitionTo
. Este código funcionará bien para la versión 0.12.X de react-router.
cris
Reaccionar enrutador 4
Puede invocar fácilmente el método push a través del contexto en v4:
this.context.router.push(this.props.exitPath);
donde contexto es:
static contextTypes = {
router: React.PropTypes.object,
};
-
Usando
BrowserRouter
el objeto de contexto de mis componentes no contiene unrouter
objeto. ¿Estoy haciendo algo mal?– pilau
1 de marzo de 2017 a las 17:54
-
¿Está configurando el contexto en el componente (el segundo bloque de arriba)?
– Chris
02/03/2017 a las 0:00
-
¡Gracias por participar! finalmente esto funcionó para mí:
router: React.PropTypes.object.isRequired
. No sé por qué no funcionó sin elisRequired
llave. También,<Link>
parece ser capaz de conseguir elhistory
contexto, pero no pude replicarlo.– pilau
2 de marzo de 2017 a las 13:36
-
Interesante: si coloca un codepen, podría ayudarlo a depurarlo si todavía está atascado
– Chris
2 de marzo de 2017 a las 13:49
-
Parece que puedes usar
this.props.history.push()
en React Router v4. Sin embargo, solo encontré esto al inspeccionar los accesorios que pasa React Router. Parece que funciona, pero no estoy seguro de si es una buena idea.– sean_j_roberts
16 de marzo de 2017 a las 14:51