react doom browserrouter javascript reactjs react-router

javascript - doom - react-router volver a una página ¿cómo se configura el historial?



react router match (16)

Mira mi ejemplo de trabajo usando React 16.0 con React-router v4 Live Example . mira el código Github

Usar withRouter e history.goBack()

Esta es la idea que estoy implementando ...

History.js

var React = require(''react''); var Router = require(''react-router''); var History = Router.History; var BackButton = React.createClass({ mixins: [ History ], render: function() { return ( <button className="back" onClick={this.history.goBack}>{this.props.children}</button> ); } }); module.exports = BackButton;

PageOne.js

<button className="back" onClick={goBack}>{this.props.children}</button> function goBack(e) { if (/* no history */) { e.preventDefault(); } else { this.history.goBack(); } }

ps lo siento, el código es demasiado grande para publicarlo todo aquí

¿Alguien puede decirme cómo puedo volver a la página anterior en lugar de una ruta específica?

Al usar este código:

var BackButton = React.createClass({ mixins: [Router.Navigation], render: function() { return ( <button className="button icon-left" onClick={this.navigateBack}> Back </button> ); }, navigateBack: function(){ this.goBack(); } });

Obtenga este error, se ignoró goBack () porque no hay historial del enrutador

Aquí están mis rutas:

// Routing Components Route = Router.Route; RouteHandler = Router.RouteHandler; DefaultRoute = Router.DefaultRoute; var routes = ( <Route name="app" path="/" handler={OurSchoolsApp}> <DefaultRoute name="home" handler={HomePage} /> <Route name="add-school" handler={AddSchoolPage} /> <Route name="calendar" handler={CalendarPage} /> <Route name="calendar-detail" path="calendar-detail/:id" handler={CalendarDetailPage} /> <Route name="info-detail" path="info-detail/:id" handler={InfoDetailPage} /> <Route name="info" handler={InfoPage} /> <Route name="news" handler={NewsListPage} /> <Route name="news-detail" path="news-detail/:id" handler={NewsDetailPage} /> <Route name="contacts" handler={ContactPage} /> <Route name="contact-detail" handler={ContactDetailPage} /> <Route name="settings" handler={SettingsPage} /> </Route> ); Router.run(routes, function(Handler){ var mountNode = document.getElementById(''app''); React.render(<Handler /> , mountNode); });


REDUX

También puede usar react-router-redux que tiene goBack() y push() .

Aquí hay un paquete de muestra para eso:

En el punto de entrada de su aplicación, necesita ConnectedRouter , y una conexión a veces difícil de conectar es el objeto de history . El middleware de Redux escucha los cambios en el historial:

import React from ''react'' import { render } from ''react-dom'' import { ApolloProvider } from ''react-apollo'' import { Provider } from ''react-redux'' import { ConnectedRouter } from ''react-router-redux'' import client from ''./components/apolloClient'' import store, { history } from ''./store'' import Routes from ''./Routes'' import ''./index.css'' render( <ApolloProvider client={client}> <Provider store={store}> <ConnectedRouter history={history}> <Routes /> </ConnectedRouter> </Provider> </ApolloProvider>, document.getElementById(''root''), )

Te mostraré una forma de conectar la history . Observe cómo se importa el historial a la tienda y también se exporta como un singleton para que pueda usarse en el punto de entrada de la aplicación:

import { createStore, applyMiddleware, compose } from ''redux'' import { routerMiddleware } from ''react-router-redux'' import thunk from ''redux-thunk'' import createHistory from ''history/createBrowserHistory'' import rootReducer from ''./reducers'' export const history = createHistory() const initialState = {} const enhancers = [] const middleware = [thunk, routerMiddleware(history)] if (process.env.NODE_ENV === ''development'') { const { devToolsExtension } = window if (typeof devToolsExtension === ''function'') { enhancers.push(devToolsExtension()) } } const composedEnhancers = compose(applyMiddleware(...middleware), ...enhancers) const store = createStore(rootReducer, initialState, composedEnhancers) export default store

El bloque de ejemplo anterior muestra cómo cargar los ayudantes de middleware react-router-redux que completan el proceso de configuración.

Creo que la siguiente parte es completamente adicional, pero la incluiré solo en caso de que alguien en el futuro encuentre beneficio:

import { combineReducers } from ''redux'' import { routerReducer as routing } from ''react-router-redux'' export default combineReducers({ routing, form, })

Uso routerReducer todo el tiempo porque me permite forzar la recarga de componentes que normalmente no se deben a shouldComponentUpdate . El ejemplo obvio es cuando tienes una barra de navegación que se supone que se actualiza cuando un usuario presiona un botón de NavLink . Si sigue ese camino, aprenderá que el método de conexión de Redux usa shouldComponentUpdate . Con routerReducer , puede usar mapStateToProps para asignar cambios de enrutamiento en la barra de mapStateToProps , y esto hará que se actualice cuando cambie el objeto del historial.

Me gusta esto:

const mapStateToProps = ({ routing }) => ({ routing }) export default connect(mapStateToProps)(Nav)

Perdóneme mientras agrego algunas palabras clave adicionales para las personas: si su componente no se actualiza correctamente, investigue shouldComponentUpdate eliminando la función de conexión y vea si soluciona el problema. Si es así, tire del routerReducer y el componente se actualizará correctamente cuando cambie la URL.

¡Para terminar, después de hacer todo eso, puede llamar a goBack() o push() cuando lo desee!

Pruébelo ahora en algún componente aleatorio:

  1. Importar en connect()
  2. Ni siquiera necesita mapStateToProps o mapDispatchToProps
  3. Importe en goBack y presione desde react-router-redux
  4. Llame this.props.dispatch(goBack())
  5. Llame this.props.dispatch(push(''/sandwich''))
  6. Experimenta emoción positiva

Si necesita más muestras, consulte: https://www.npmjs.com/package/react-router-redux


Actualización con React v16 y ReactRouter v4.2.0 (octubre de 2017):

class BackButton extends Component { static contextTypes = { router: () => true, // replace with PropTypes.object if you use them } render() { return ( <button className="button icon-left" onClick={this.context.router.history.goBack}> Back </button> ) } }

Actualización con React v15 y ReactRouter v3.0.0 (agosto de 2016):

var browserHistory = ReactRouter.browserHistory; var BackButton = React.createClass({ render: function() { return ( <button className="button icon-left" onClick={browserHistory.goBack}> Back </button> ); } });

Creó un violín con un ejemplo un poco más complejo con un iframe incrustado: https://jsfiddle.net/kwg1da3a/

React v14 y ReacRouter v1.0.0 (10 de septiembre de 2015)

Puedes hacerlo:

var React = require("react"); var Router = require("react-router"); var SomePage = React.createClass({ ... contextTypes: { router: React.PropTypes.func }, ... handleClose: function () { if (Router.History.length > 1) { // this will take you back if there is history Router.History.back(); } else { // this will take you to the parent route if there is no history, // but unfortunately also add it as a new route var currentRoutes = this.context.router.getCurrentRoutes(); var routeName = currentRoutes[currentRoutes.length - 2].name; this.context.router.transitionTo(routeName); } }, ...

Debe tener cuidado de tener el historial necesario para regresar. Si aciertas directamente en la página y luego presionas de nuevo, volverás al historial del navegador antes de tu aplicación.

Esta solución se encargará de ambos escenarios. Sin embargo, no manejará un iframe que pueda navegar dentro de la página (y agregarse al historial del navegador), con el botón Atrás. Francamente, creo que es un error en el enrutador de reacción. Problema creado aquí: https://github.com/rackt/react-router/issues/1874


  1. importar con withRouter

    import React from ''react'' import { browserHistory } from ''react-router'' export const Test = () => ( <div className=""> <button onClick={browserHistory.goBack}>Back</button> </div> )

  2. Exporte su componente como:

    import { withRouter } from ''react-router-dom'';

  3. Ejemplo, al hacer clic en el botón, llame a goBack :

    export withRouter(nameofcomponent)

Probado en react-router-dom v4.3


Creo que solo necesita habilitar BrowserHistory en su enrutador inicializándolo así: <Router history={new BrowserHistory}> .

Antes de eso, debe requerir BrowserHistory de ''react-router/lib/BrowserHistory''

Espero que eso ayude !

ACTUALIZACIÓN: ejemplo en ES6

const BrowserHistory = require(''react-router/lib/BrowserHistory'').default; const App = React.createClass({ render: () => { return ( <div><button onClick={BrowserHistory.goBack}>Go Back</button></div> ); } }); React.render(( <Router history={BrowserHistory}> <Route path="/" component={App} /> </Router> ), document.body);


En react-router v4.x puede usar history.goBack que es equivalente a history.go(-1) .

App.js

import React from "react"; import { render } from "react-dom"; import { BrowserRouter as Router, Route, Link } from "react-router-dom"; import Home from "./Home"; import About from "./About"; import Contact from "./Contact"; import Back from "./Back"; const styles = { fontFamily: "sans-serif", textAlign: "left" }; const App = () => ( <div style={styles}> <Router> <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> <hr /> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/contact" component={Contact} /> <Back />{/* <----- This is component that will render Back button */} </div> </Router> </div> ); render(<App />, document.getElementById("root"));

Back.js

import React from "react"; import { withRouter } from "react-router-dom"; const Back = ({ history }) => ( <button onClick={history.goBack}>Back to previous page</button> ); export default withRouter(Back);

Demostración: https://codesandbox.io/s/ywmvp95wpj

Recuerde que al usar el history sus usuarios pueden irse porque history.goBack() puede cargar una página que el visitante ha visitado antes de abrir su aplicación.

Para evitar tal situación como se describe anteriormente, he creado una biblioteca simple react-router-last-location que observa la última ubicación de sus usuarios.

El uso es muy sencillo. Primero debe instalar react-router-dom y react-router-last-location desde npm .

npm install react-router-dom react-router-last-location --save

Luego use LastLocationProvider como se muestra a continuación:

App.js

import React from "react"; import { render } from "react-dom"; import { BrowserRouter as Router, Route, Link } from "react-router-dom"; import { LastLocationProvider } from "react-router-last-location"; // ↑ // | // | // // Import provider // import Home from "./Home"; import About from "./About"; import Contact from "./Contact"; import Back from "./Back"; const styles = { fontFamily: "sans-serif", textAlign: "left" }; const App = () => ( <div style={styles}> <h5>Click on About to see your last location</h5> <Router> <LastLocationProvider>{/* <---- Put provider inside <Router> */} <div> <ul> <li><Link to="/">Home</Link></li> <li><Link to="/about">About</Link></li> <li><Link to="/contact">Contact</Link></li> </ul> <hr /> <Route exact path="/" component={Home} /> <Route path="/about" component={About} /> <Route path="/contact" component={Contact} /> <Back /> </div> </LastLocationProvider> </Router> </div> ); render(<App />, document.getElementById("root"));

Back.js

import React from "react"; import { Link } from "react-router-dom"; import { withLastLocation } from "react-router-last-location"; // ↑ // | // | // // `withLastLocation` higher order component // will pass `lastLocation` to your component // // | // | // ↓ const Back = ({ lastLocation }) => ( lastLocation && <Link to={lastLocation || ''/''}>Back to previous page</Link> ); // Remember to wrap // your component before exporting // // | // | // ↓ export default withLastLocation(Back);

Demostración: https://codesandbox.io/s/727nqm99jj


Este código hará el truco por ti.

this.context.router.history.goBack()


Este es un componente de BackButton que funciona (Reaccionar 0.14):

import React from ''react''; import FontAwesome from ''react-fontawesome''; import { Router, RouterContext, Link, browserHistory } from ''react-router''; export default class Header extends React.Component { render() { return ( <div id="header"> <div className="header-left"> { this.props.hasBackButton && <FontAwesome name="angle-left" className="back-button" onClick={this.context.router.goBack} /> } </div> <div>{this.props.title}</div> </div> ) } } Header.contextTypes = { router: React.PropTypes.object }; Header.defaultProps = { hasBackButton: true }; Header.propTypes = { title: React.PropTypes.string };

Por supuesto, puede hacer algo como esto si no hay historial:

import React, { Component } from ''react''; import { withRouter } from ''react-router-dom'' import ''./App.css'' class History extends Component { handleBack = () => { this.props.history.goBack() } handleForward = () => { console.log(this.props.history) this.props.history.go(+1) } render() { return <div className="container"> <div className="row d-flex justify-content-between"> <span onClick={this.handleBack} className="d-flex justify-content-start button"> <i className="fas fa-arrow-alt-circle-left fa-5x"></i> </span> <span onClick={this.handleForward} className="d-flex justify-content-end button"> <i className="fas fa-arrow-alt-circle-right fa-5x"></i> </span> </div> </div> } } export default withRouter(History)


Llame al siguiente componente así:

<BackButton history={this.props.history} />

Y aquí está el componente:

import React, { Component } from ''react'' import PropTypes from ''prop-types'' class BackButton extends Component { constructor() { super(...arguments) this.goBack = this.goBack.bind(this) } render() { return ( <button onClick={this.goBack}> Back </button> ) } goBack() { this.props.history.goBack() } } BackButton.propTypes = { history: PropTypes.object, } export default BackButton

Estoy usando:

"react": "15.6.1" "react-router": "4.2.0"


Lo que funcionó para mí fue importar con Router en la parte superior de mi archivo;

import { withRouter } from ''react-router-dom'' this.props.history.goBack();

Luego, úselo para ajustar la función exportada al final de mi archivo;

"react": "^15.6.1", "react-dom": "^15.6.1", "react-router": "^4.2.0", "react-router-dom": "^4.2.2",

Lo que luego me permitió acceder al accesorio de historia del enrutador. ¡Código de muestra completo a continuación!

import { withRouter } from ''react-router-dom''


Método ES6 sin mixins utilizando react-router, función sin estado.

<button onClick={this.props.history.goBack}>Back</button>


Para react-router v2.x esto ha cambiado. Esto es lo que estoy haciendo para ES6:

import React, { Fragment, Component } from ''react'' class PageOne extends Component { componentDidMount(){ if(this.props.location.state && this.props.location.state.from != ''/pageone'') this.props.history.push({ pathname: ''/pageone'', state: { from: this.props.location.pathname } }); } render() { return ( <Fragment> <div className="container-fluid"> <div className="row d-flex justify-content-center"> <h2>Page One</h2> </div> </div> </Fragment> ) } } export default PageOne


Simplemente use así

<span onClick={() => this.props.history.goBack()}>Back</span>


this.props.history.goBack ();

Esto funciona con el historial del navegador y Hash.


export default withRouter(WebSitePageTitleComponent)

Estoy usando estas versiones

import React, { Component } from ''react'' import { withRouter } from ''react-router-dom'' import PropTypes from ''prop-types'' class TestComponent extends Component { constructor(props) { super(props) this.handleClick = this.handleClick.bind(this) } handleClick() { event.preventDefault() this.props.history.goBack() } render() { return ( <div className="page-title"> <a className="container" href="/location" onClick={this.handleClick}> <h1 className="page-header"> { this.props.title } </h1> </a> </div> ) } } const { string, object } = PropTypes TestComponent.propTypes = { title: string.isRequired, history: object } export default withRouter(TestComponent)


this.context.router.goBack()

¡No se requiere mezcla de navegación!