withrouter react hashrouter doom reactjs react-router

reactjs - hashrouter - Navegando programáticamente en React-Router v4



react-router-dom redirect (9)

No podía esperar y aproveché para usar la última versión alfa de react-router v4. El <BrowserRouter/> es excelente para mantener su UI en sincronía con el historial del navegador, pero ¿cómo lo uso para navegar programáticamente?


El enrutador enviará un objeto de history a su componente en el hash de props . Entonces en tu componente, simplemente hazlo:

this.props.history.push(''/mypath'')

Aquí hay un ejemplo completo:

En App.js :

import React from ''react'' import {BrowserRouter as Router, Route} from ''react-router-dom'' import Login from ''./Login'' export default class App extends React.Component { render() { return ( <Router> <div> <Route exact path=''/login'' component={Login} /> </div> </Router> ) } }

En Login.js :

import React, {PropTypes} from ''react'' export default class Login extends React.Component { constructor(props) { super(props) this.handleLogin = this.handleLogin.bind(this) } handleLogin(event) { event.preventDefault() // do some login logic here, and if successful: this.props.history.push(`/mypath`) } render() { return ( <div> <form onSubmit={this.handleLogin}> <input type=''submit'' value=''Login'' /> </form> </div> ) } }


El uso de withRouter agregará propiedades de enrutador a su componente, luego puede acceder al history y usar push como lo hizo con v3:

import React from ''react''; import { withRouter } from ''react-router-dom''; class Form extends React.Component { constructor(props) { super(props); this.state = { input: '''', }; this._submit = this._submit.bind(this); } render() { return ( <form onSubmit={this._submit}> <input type="text" onChange={(event) => this.setState({input: event.target.value})}/> <button type="submit">Submit</button> </form> ); } _submit(event) { event.preventDefault(); this.props.history.push(`/theUrlYouWantToGoTo`); } } export default withRouter(Form);


En el pasado, es posible que haya utilizado browserHistory para insertar una nueva ruta. Esto no funcionará con react-router v4. En su lugar, debe hacer uso del context de React y del método transitionTo router .

Aquí hay un ejemplo simple:

import React from ''react''; class NavigateNext extends React.Component { constructor() { super(); this.navigateProgramatically = this.navigateProgramatically.bind(this); } navigateProgramatically(e) { e.preventDefault(); this.context.router.transitionTo(e.target.href) } render() { return ( <Link to={"/next-page"} onClick={this.navigateProgramatically} >Continue</Link> ); } } NavigateNext.contextTypes = { router: React.PropTypes.object };

transitionTo es solo uno de los métodos de router disponibles. router objeto router también contiene blockTransitions(getPromptMessage) , createHref(to) y replaceWith(loc) que vale la pena consultar.

Aquí está el tutorial de react-router oficial que menciona el método anterior. Si desea obtener más información sobre el uso del context react , consulte los docs .


Encontré usar state, un operador ternario y <Redirect> funcionó mejor. Creo que esta es también la forma preferida, ya que está más cerca de la forma en que v4 está configurado.

En el constructor ()

this.state = { redirectTo: null } this.clickhandler = this.clickhandler.bind(this);

En el render ()

render(){ return ( <div> { this.state.redirectTo ? <Redirect to={{ pathname: this.state.redirectTo }} /> : ( <div> .. <button onClick={ this.clickhandler } /> .. </div> ) }

En el manipulador de clics ()

this.setState({ redirectTo: ''/path/some/where'' });

Espero eso ayude. Házmelo saber.


No tengo suficiente reputación para comentar, pero en respuesta a la pregunta de @singleity, debe incluir las propiedades de contexto que desea poner a disposición en la propiedad estática de los contextTypes context context de la clase de componente.

De docs :

Si contextTypes no está definido, el contexto será un objeto vacío.

En este caso:

class NavigateNext extends React.Component { // ... static contextTypes = { router: PropTypes.object } // ... }

A diferencia de propTypes , propTypes hace que React se comporte de manera diferente y no solo para la verificación de tipo.


Si necesita acceder al historial fuera de los componentes (por ejemplo, en acciones de reducción), react-router ha publicado su solución original here .

Básicamente, debes crear tu propio objeto de historial :

import { createBrowserHistory } from ''history''; const history = createBrowserHistory();

Y páselo a tu enrutador:

import { Router } from ''react-router-dom''; ReactDOM.render(( <Router history={history}> // <<-- the history object <App/> </Router> ), document.getElementById(''root''))

Nota: ¡tiene que usar un enrutador simple en lugar de BrowserRouter o HashRouter aquí!

Si exporta el history ahora, puede trabajar con él en cualquier lugar:

import history from ''./history''; history.push(''/home'');


Si necesita navegar fuera de un componente en una ubicación que no puede pasar en el objeto de historial desde un componente similar a cómo lo haría con browserHistory en versiones anteriores, puede hacer lo siguiente.

Primero crea un módulo de historial

History.js:

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

Luego, cuando declare el enrutador, asegúrese de importar el Enrutador desde el router de reacción y no reaccione-enrutador-dom (que es solo una versión del reiniciador-enrutador pero crea el objeto de historial automáticamente) y pase el módulo de historial que acaba de crear

Root.js (o donde sea que hagas esto):

import Router from ''react-router/Router'' import history from ''./history'' ... class Root extends Component{ render() { return ( <Router history={history}> ... </Router> ); } }

Ahora su aplicación usará el historial creado personalizado que creó. Ahora puede importar ese módulo de historial en cualquier lugar y simplemente hacer history.replace y demás tal como lo haría con browserHistory en el pasado.

SomeModule.js:

import history from ''./history''; export default ()=>{ // redirecting to login page using history without having to pass it in // from a component history.replace(''/login'') }

Por supuesto, esta no es la manera recomendada, ya que el uso de browserHistory en las versiones anteriores no era el método recomendado, ya que las funciones como el procesamiento del lado del servidor no funcionarían, pero si no te importa, esta suele ser la solución adecuada.

Un beneficio adicional al hacer esto es que podría aumentar el objeto de historial para que las cosas queden paramétricas de cadena de consulta analizadas como esta, por ejemplo:

import createBrowserHistory from ''history/createBrowserHistory'' import queryString from ''query-string''; const history = createBrowserHistory(); history.location.query = queryString.parse(history.location.search); history.listen(() => { history.location.query = queryString.parse(history.location.search); }); export default history;


react-router v4 beta se lanza y la API cambia un poco. En lugar de this.context.router.transitionTo(e.target.href) Haga, this.context.router.push(e.target.href) si está utilizando la última versión.

Enlace al nuevo documento: https://reacttraining.com/react-router/#context.router


usar withRouter :

import React, { PropTypes } from ''react'' import { withRouter } from ''react-router'' // A simple component that shows the pathname of the current location class ShowTheLocation extends React.Component { static propTypes = { match: PropTypes.object.isRequired, location: PropTypes.object.isRequired, history: PropTypes.object.isRequired } render() { const { match, location, history } = this.props return ( <div>You are now at {location.pathname}</div> ) } } // Create a new component that is "connected" (to borrow redux // terminology) to the router. const ShowTheLocationWithRouter = withRouter(ShowTheLocation)