【问题标题】:react-router go back a page how do you configure history?react-router 返回一个页面 你如何配置历史?
【发布时间】:2015-09-04 01:56:30
【问题描述】:

谁能告诉我如何返回上一页而不是特定路线?

使用此代码时:

var BackButton = React.createClass({

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

  navigateBack: function(){
    this.goBack();
  }
});

收到此错误,goBack() 被忽略,因为没有路由器历史记录

这是我的路线:

// 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);
 });

【问题讨论】:

  • 如果您找到了解决方案,请在此处分享。谢谢。

标签: javascript reactjs react-router


【解决方案1】:

更新 React v16 和 ReactRouter v4.2.0(2017 年 10 月):

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>
    )
  }
}

更新 React v15 和 ReactRouter v3.0.0(2016 年 8 月):

var browserHistory = ReactRouter.browserHistory;

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

使用嵌入式 iframe 创建了一个更复杂的示例:https://jsfiddle.net/kwg1da3a/

React v14 和 ReacRouter v1.0.0(2015 年 9 月 10 日)

你可以这样做:

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);
    }
  },
  ...

你需要小心你有必要的历史来回溯。如果您直接点击页面然后回击,它将带您回到应用之前的浏览器历史记录中。

此解决方案将处理这两种情况。但是,它不会处理可以使用后退按钮在页面内导航(并添加到浏览器历史记录)的 iframe。坦率地说,我认为这是 react-router 中的一个错误。此处创建的问题:https://github.com/rackt/react-router/issues/1874

【讨论】:

  • 如果有办法在不使用上下文的情况下做到这一点会很好吗?
  • 另外,根据设置,可能使用 this.props.history.goBack 而不是 this.context.router.history.goBack
【解决方案2】:

使用 React Hooks

进口:

import { useHistory } from "react-router-dom";

在无状态组件中:

let history = useHistory();

调用事件:

history.goBack()

在事件按钮中使用的示例:

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

<button onClick={() => history.goBack()}>Back</button>

【讨论】:

  • 感谢您提及这一点,因为我喜欢钩子。到目前为止,我一直在使用 withRouter。
  • 'useHistory' 不是从 'react-router-dom' 导出的。
  • @Hunter 谢谢我在onClick={history.goBack()} 然后它开始点击而不点击
  • 按原样传递函数也可以&lt;button onClick={history.goBack}&gt;Back&lt;/button&gt;(不带括号)
【解决方案3】:

我认为您只需要通过像这样初始化路由器来启用 BrowserHistory:&lt;Router history={new BrowserHistory}&gt;

在此之前,您应该要求 BrowserHistory 来自 'react-router/lib/BrowserHistory'

希望对你有帮助!

更新: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);

【讨论】:

  • 嗨,我们面临同样的问题。您能否详细解释一下。谢谢
  • 正确答案如何?这甚至不能回答这个问题。 @轰炸机
  • 对于任何阅读本文的人。如果您想从子组件执行此操作。您可以在this.props.history 找到历史记录对象。所以,代码变成了this.props.history.goBack
  • react-router 4 怎么样?我认为它不再支持 BrowserHistory。
  • 从 react-router-dom 版本 5 开始,历史记录是由 BrowserRouter 隐式创建的,并且可以通过 props 获得,您可以通过 props.history 访问它。
【解决方案4】:
  1. 导入withRouter

    import { withRouter } from 'react-router-dom';
    
  2. 将您的组件导出为:

    export withRouter(nameofcomponent) 
    
  3. 例如,点击按钮时,调用goBack

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

react-router-dom v4.3 上测试

【讨论】:

  • 顺便说一句,即使没有导入或使用withRouter,它也对我有用。也许我们只是在使用浏览器历史原生 API。但是这样可以吗??
  • 这是一个很好的解决方案。当用户使用直接 URL 登陆页面时唯一的问题 -> 它会破坏应用程序,因为它没有历史记录。
  • 最好的解释在这里
  • @MichaelFreidgeim 你能上传你的代码 sn-p 以便我检查和验证
【解决方案5】:
this.context.router.goBack()

不需要导航混合!

【讨论】:

  • 这仍然适用于 React Router v4,但它是 this.context.router.history.goBack。 (+历史)
  • 使用 react-router-dom: "v4.2.2" 和 import { withRouter } from 'react-router-dom'; 使用 this.props.history.goBack();
  • 除了@felansu 的评论,您还需要使用Router 导出组件,如答案stackoverflow.com/a/49130220/3123338中所述
【解决方案6】:

使用 react-router、无状态函数的没有 mixins 的 ES6 方法。

import React from 'react'
import { browserHistory } from 'react-router'

export const Test = () => (
  <div className="">
    <button onClick={browserHistory.goBack}>Back</button>
  </div>
)

【讨论】:

【解决方案7】:

返回特定页面

  import { useHistory } from "react-router-dom";

  const history = useHistory();
  
  const routeChange = () => {
    let path = '/login';
    history.push(path);
  };

返回上一页

  import { useHistory } from "react-router-dom";

  const history = useHistory();
  
  const routeChange = () => {
    history.goBack()
  };

【讨论】:

  • 谢谢,这是 2020 年的绝佳答案!接受的答案是 2015 年。
【解决方案8】:

React Router v6

useNavigateHook 是现在返回的推荐方式:

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

function App() {
  const navigate = useNavigate();

  return (
    <>
      <button onClick={() => navigate(-1)}>go back</button>
      <button onClick={() => navigate(1)}>go forward</button>
    </>
  );
}

Codesandbox sample

返回/转发多个历史堆栈条目:
<button onClick={() => navigate(-2)}>go two back</button>
<button onClick={() => navigate(2)}>go two forward</button>
前往具体路线:
navigate("users") // go to users route, like history.push
navigate("users", { replace: true }) // go to users route, like history.replace
navigate("users", { state }) // go to users route, pass some state in

useNavigate replaces useHistory to support 即将推出 React Suspense/Concurrent 模式更好。

【讨论】:

  • 我尝试了这个但我得到了错误:Attempted import error: 'useNavigate' is not exported from 'react-router-dom'.
  • @Geek 不错。使用v6.0.0-beta.0,开发人员使history 包成为对等依赖项。看看更新后的 Codesandbox,它现在又可以使用了。
【解决方案9】:

这适用于浏览器和哈希历史记录。

this.props.history.goBack();

【讨论】:

    【解决方案10】:

    查看我使用 React 16.0 和 React-router v4 的工作示例。查看代码Github

    使用withRouterhistory.goBack()

    这是我正在实施的想法......

    History.js

    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)
    

    PageOne.js

    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
    

    附言抱歉,代码太大了,不能全部贴在这里

    【讨论】:

    • 这应该是 19 年接受的答案。 React Router 提供了一个名为“withRouter”的高阶组件(HOC),因此您可以包装您的组件以访问诸如历史和位置之类的道具。
    • 是的,就像 HOC 中的 withRouter 一样,在你包装你的组件部分时,将提供历史和位置数据。没有什么具有挑战性的东西可以一直阅读并且永远不会安定下来。
    • 请问您为什么将加号传递给go 函数:history.go(+1)history.go(1) 应该够了。
    • 老实说,我只是尝试在没有 withRouter 的情况下使用这个 history.goBack() 已经成功了
    【解决方案11】:

    这是一个有效的 BackButton 组件(React 0.14):

    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;
    

    如果没有历史记录,你当然可以这样做:

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

    【讨论】:

      【解决方案12】:

      对于 react-router v2.x 这已经改变了。这是我为 ES6 做的事情:

      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
      };
      

      【讨论】:

        【解决方案13】:

        在 react-router v4.x 中,您可以使用 history.goBack,它等同于 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);
        

        演示: https://codesandbox.io/s/ywmvp95wpj

        请记住,通过使用history,您的用户可以离开,因为history.goBack() 可以加载访问者在打开您的应用程序之前访问过的页面。


        为了防止出现上述情况,我创建了一个简单的库 react-router-last-location 来监视您的用户的最后位置。

        使用非常简单。 首先你需要从npm安装react-router-domreact-router-last-location

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

        然后使用LastLocationProvider如下:

        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);
        

        演示: https://codesandbox.io/s/727nqm99jj

        【讨论】:

        • 您如何将 LastLocation 对象拉入需要它的组件中-也就是说,我想以编程方式使用它,而不是像您的示例那样在某些显示的输出中使用它: if(lastLocation == '关于')
        • 不确定我是否理解正确,所以如果我错了,请纠正我。你想在 React 之外使用lastLocation 还是说I'd like to use it programmatically,你想要像import { lastLocation } from '...' 一样导入它吗?
        【解决方案14】:

        对我有用的是在我的文件顶部导入 withRouter;

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

        然后用它把导出的函数包装在我的文件底部;

        export default withRouter(WebSitePageTitleComponent)
        

        然后允许我访问路由器的历史道具。完整的示例代码如下!

        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)
        

        【讨论】:

          【解决方案15】:
          import { withRouter } from 'react-router-dom'
          
          this.props.history.goBack();
          

          我正在使用这些版本

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

          【讨论】:

            【解决方案16】:

            第一步

            import { useHistory } from "react-router-dom";`
            

            第二步

            let history = useHistory();
            

            第三步

            const goToPreviousPath = (e) => {
               e.preventDefault();
               history.goBack()
            }
            

            第四步

            <Button
              onClick={goToPreviousPath}
            >
              Back
            </Button>
            

            【讨论】:

              【解决方案17】:

              REDUX

              你也可以使用react-router-redux,它有goBack()push()

              这是一个采样包:

              在您的应用程序的入口点中,您需要ConnectedRouter,而连接起来有时很棘手的连接是history 对象。 Redux 中间件监听历史变化:

              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'),
              )
              

              我将向您展示一种连接history 的方法。请注意历史是如何导入到 store 中的,也可以作为单例导出的,以便在应用程序的入口点中使用它:

              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
              

              上面的示例块显示了如何加载完成设置过程的react-router-redux 中间件助手。

              我认为下一部分完全是额外的,但我会包括它以防万一将来有人从中受益:

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

              我一直使用routerReducer,因为它允许我强制重新加载通常不会由于shouldComponentUpdate 而导致的组件。最明显的例子是当用户按下NavLink 按钮时应该更新导航栏。如果你沿着这条路走,你会发现 Redux 的连接方法使用了shouldComponentUpdate。使用routerReducer,您可以使用mapStateToProps 将路由更改映射到导航栏,这将在历史对象更改时触发更新。

              像这样:

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

              请原谅我为人们添加了一些额外的关键字:如果您的组件没有正确更新,请通过删除连接函数来调查 shouldComponentUpdate 并查看它是否解决了问题。如果是这样,请拉入routerReducer,当 URL 更改时,组件将正确更新。

              最后,完成所有这些之后,您可以随时致电goBack()push()

              现在在一些随机组件中尝试一下:

              1. 导入connect()
              2. 你甚至不需要mapStateToPropsmapDispatchToProps
              3. 在goBack中导入并从react-router-redux推送
              4. 致电this.props.dispatch(goBack())
              5. 致电this.props.dispatch(push('/sandwich'))
              6. 体验积极的情绪

              如果您需要更多采样,请查看:https://www.npmjs.com/package/react-router-redux

              【讨论】:

                【解决方案18】:

                像这样简单地使用

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

                【讨论】:

                  【解决方案19】:

                  唯一对我有用的解决方案是最简单的。无需额外导入。

                  <a href="#" onClick={() => this.props.history.goBack()}>Back</a>
                  

                  Tks,IamMHussain

                  【讨论】:

                  • 非常好。简单谦虚
                  【解决方案20】:

                  React Router 使用 HTML5 History API,它建立在浏览器历史 API 的基础上,提供了一个我们可以在 React 应用程序中轻松使用的接口。 History API 。所以无需导入任何东西(useHistory 等)

                  对于功能组件:

                  <button onClick={()=>{ window.history.back() }}> Back </button>
                  

                  对于类组件:

                  <button onClick={()=>{ this.window.history.back() }}> Back </button>
                  

                  【讨论】:

                    【解决方案21】:

                    像这样调用以下组件:

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

                    这是组件:

                    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
                    

                    我正在使用:

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

                    【讨论】:

                      【解决方案22】:

                      这段代码将为您解决问题。

                      this.context.router.history.goBack()
                      

                      【讨论】:

                        【解决方案23】:

                        根据https://reacttraining.com/react-router/web/api/history

                        对于"react-router-dom": "^5.1.2",

                        const { history } = this.props;
                        <Button onClick={history.goBack}>
                          Back
                        </Button>
                        
                        YourComponent.propTypes = {
                          history: PropTypes.shape({
                            goBack: PropTypes.func.isRequired,
                          }).isRequired,
                        };
                        

                        【讨论】:

                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2022-12-03
                          • 2022-01-13
                          • 2018-12-26
                          • 2021-10-24
                          相关资源
                          最近更新 更多