javascript - training - React-router: ¿Cómo invocar manualmente Link?
react training react router dom (6)
Soy nuevo en ReactJS y en React-Router.
Tengo un componente que recibe a través de accesorios un objeto
<Link/>
de
react-router
.
Cada vez que el usuario hace clic en el botón ''siguiente'' dentro de este componente, quiero invocar el objeto
<Link/>
manualmente.
En este momento, estoy usando
referencias
para acceder a la
instancia de respaldo
y haciendo clic manualmente en la etiqueta ''a'' que genera
<Link/>
.
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>
...
);
}
});
...
React Router v4 - Redirect Component (actualizado 2017/04/15)
La forma recomendada de v4 es permitir que su método de renderizado atrape una redirección. Use el estado o los accesorios para determinar si el componente de redireccionamiento debe mostrarse (que luego desencadena 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 de referencia del enrutador
También puede aprovechar el contexto del
Router
que está expuesto al componente Reaccionar.
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 debajo del 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 notables con los ciclos de vida, pero siempre debe volver a generar el enrutador, al igual que en v2.
Esto puede ser útil para 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'');
El último
BrowserRouter
extenderá:
https://github.com/ReactTraining/react-router/blob/master/packages/react-router-dom/modules/BrowserRouter.js
React Router v2
Empuje un nuevo estado a la instancia de
browserHistory
:
import {browserHistory} from ''react-router'';
// ...
browserHistory.push(''/sample'');
Referencia: https://github.com/reactjs/react-router/blob/master/docs/guides/NavigatingOutsideOfComponents.md
React Router 4
Puede invocar fácilmente el método push a través del contexto en v4:
this.context.router.push(this.props.exitPath);
donde el contexto es:
static contextTypes = {
router: React.PropTypes.object,
};
Ok, creo que pude encontrar una solución adecuada para eso.
Ahora, en lugar de enviar
<Link/>
como
accesorio
a Document, envío
<NextLink/>
que es un contenedor personalizado para el Link del enrutador de reacción.
Al hacer eso, puedo tener la flecha hacia la derecha como parte de la estructura de Enlace mientras evito tener el 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
lugar de
this.context.transitionTo
.
Este código funcionará bien para la versión de enrutador reactivo 0.12.X.
React Router 4 incluye un
withRouter
HOC
que le da acceso al objeto de
history
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(''/'')
}
render() {
<div className="foo">
<button onClick={this.goHome} />
</div>
}
}
export default withRouter(Foo)
de nuevo, esto es JS :) esto todavía funciona ...
var linkToClick = document.getElementById(''something'');
linkToClick.click();
<Link id="something" to={/somewhaere}> the link </Link>
o incluso puede intentar ejecutar onClick this (solución más violenta):
window.location.assign("/sample");