【问题标题】:How to push to History in React Router v4?如何在 React Router v4 中推送到历史记录?
【发布时间】:2017-07-30 18:42:46
【问题描述】:

在当前版本的 React Router (v3) 中,我可以接受服务器响应并使用 browserHistory.push 转到相应的响应页面。但是,这在 v4 中不可用,我不确定处理此问题的适当方法是什么。

在此示例中,使用 Redux,components/app-product-form.js 在用户提交表单时调用 this.props.addProduct(props)。当服务器返回成功时,用户被带到购物车页面。

// actions/index.js
export function addProduct(props) {
  return dispatch =>
    axios.post(`${ROOT_URL}/cart`, props, config)
      .then(response => {
        dispatch({ type: types.AUTH_USER });
        localStorage.setItem('token', response.data.token);
        browserHistory.push('/cart'); // no longer in React Router V4
      });
}

如何从 React Router v4 的函数重定向到购物车页面?

【问题讨论】:

  • 只是从提供的最后一个解决方案和 GitHub 上 React Router 问题中的建议添加到这一点,使用 context 手动传递你需要的东西是“不行的”。除非我是图书馆作者,否则不需要使用它。事实上,Facebook 建议不要这样做。
  • @Chris 你找到解决方案了吗?我需要推送到一个不同的组件,就像你在这里解释的一样
  • 为什么我们不能使用 windows.location.href= URL?使用它来更改网址和重定向有什么问题吗?
  • @Shan 如果您使用 location.href,我相信您会丢失应用程序状态。它也不适合移动设备。
  • 使用@Shan 的建议,例如( windows.location.href=("/") )在移动设备上的问题为零。按预期工作。 *在我的特定用例中丢失应用程序状态不是问题。

标签: reactjs react-router react-router-v4


【解决方案1】:

React Router v4 与 v3(及更早版本)根本不同,您不能像以前那样使用browserHistory.push()

如果您想了解更多信息,This discussion 似乎相关:

  • 创建一个新的browserHistory 将不起作用,因为<BrowserRouter> 创建了它自己的历史实例,并监听它的变化。因此,不同的实例会更改 url,但不会更新 <BrowserRouter>
  • browserHistory 在 v4 中没有被 react-router 公开,仅在 v2 中。

相反,您有几个选择:

  • 使用withRouter高阶组件

    相反,您应该使用withRouter 高阶组件,并将其包装到将推送到历史记录的组件中。例如:

    import React from "react";
    import { withRouter } from "react-router-dom";
    
    class MyComponent extends React.Component {
      ...
      myFunction() {
        this.props.history.push("/some/Path");
      }
      ...
    }
    export default withRouter(MyComponent);
    

    查看official documentation 了解更多信息:

    您可以通过 withRouter 高阶组件访问history 对象的属性和最接近的<Route>match。每次路由更改时,withRouter 都会重新渲染其组件,使用与 <Route> 相同的道具渲染道具:{ match, location, history }


  • 使用context API

    使用上下文可能是最简单的解决方案之一,但作为实验性 API,它不稳定且不受支持。只有在其他一切都失败时才使用它。这是一个例子:

    import React from "react";
    import PropTypes from "prop-types";
    
    class MyComponent extends React.Component {
      static contextTypes = {
        router: PropTypes.object
      }
      constructor(props, context) {
         super(props, context);
      }
      ...
      myFunction() {
        this.context.router.history.push("/some/Path");
      }
      ...
    }
    

    查看上下文中的official documentation

    如果您希望您的应用程序稳定,请不要使用上下文。它是一个实验性 API,可能会在未来的 React 版本中中断。

    如果您不顾这些警告仍坚持使用上下文,请尝试将您对上下文的使用隔离到一个小区域,并尽可能避免直接使用上下文 API,以便在 API 更改时更容易升级。

【讨论】:

  • 是的,我试过了。谢谢你的提问。 :-) 那么如何将上下文引入到这个动作函数中呢?到目前为止,它的出现是未定义的。
  • 我已经研究这个主题几天了,但一直没能成功。即使使用上面的示例,我仍然在上下文中不断收到路由器未定义。我目前正在使用 react v15.5.10、react-router-dom v4.1.1、prop-types 15.5.10。这方面的文档很少而且不是很清楚。
  • @Stu 这应该可以工作this.context.router.history.push('/path');
  • 这并不能回答所提出的问题,即如何访问组件的 history.push OUTSIDE。在组件之外使用 withRouter 或上下文不是选项。
  • 从 React 16.3 开始,上下文 API 不再是实验性的。 React 的博客文章 React v16.3.0: New lifecycles and context API 以获取有关该版本的更多信息。
【解决方案2】:

我就是这样做的:

import React, {Component} from 'react';

export default class Link extends Component {
    constructor(props) {
        super(props);
        this.onLogout = this.onLogout.bind(this);
    }
    onLogout() {
        this.props.history.push('/');
    }
    render() {
        return (
            <div>
                <h1>Your Links</h1>
                <button onClick={this.onLogout}>Logout</button>
            </div>
        );
    }
}

使用this.props.history.push('/cart'); 重定向到购物车页面,它将被保存在历史对象中。

享受吧,迈克尔。

【讨论】:

  • 是的,看起来在组件内你可以推送就好了。影响组件外部导航的唯一方法是使用重定向。
  • 这并不能回答所提出的问题,即如何访问组件的 history.push OUTSIDE。在组件之外使用 this.props.history 不是一个选项。
【解决方案3】:

this.context.history.push 将不起作用。

我设法让 push 像这样工作:

static contextTypes = {
    router: PropTypes.object
}

handleSubmit(e) {
    e.preventDefault();

    if (this.props.auth.success) {
        this.context.router.history.push("/some/Path")
    }

}

【讨论】:

  • 这并不能回答所提出的问题,即如何访问组件的 history.push OUTSIDE。在组件之外使用 this.context 不是一个选项。
【解决方案4】:

如果你使用 Redux,那么我会推荐使用 npm 包react-router-redux。它允许您调度 Redux 商店导航操作。

您必须按照他们的Readme file 中的说明创建商店。

最简单的用例:

import { push } from 'react-router-redux'

this.props.dispatch(push('/second page'));

容器/组件的第二个用例:

容器:

import { connect } from 'react-redux';
import { push } from 'react-router-redux';

import Form from '../components/Form';

const mapDispatchToProps = dispatch => ({
  changeUrl: url => dispatch(push(url)),
});

export default connect(null, mapDispatchToProps)(Form);

组件:

import React, { Component } from 'react';
import PropTypes from 'prop-types';

export default class Form extends Component {
  handleClick = () => {
    this.props.changeUrl('/secondPage');
  };

  render() {
    return (
      <div>
        <button onClick={this.handleClick}/>
      </div>Readme file
    );
  }
}

【讨论】:

  • 与 react-router-redux 一起工作,除非您使用的是 next 版本,目前仍在开发中!
【解决方案5】:

在这种情况下,您将道具传递给您的 thunk。所以你可以简单地调用

props.history.push('/cart')

如果不是这种情况,您仍然可以从组件传递历史记录

export function addProduct(data, history) {
  return dispatch => {
    axios.post('/url', data).then((response) => {
      dispatch({ type: types.AUTH_USER })
      history.push('/cart')
    })
  }
}

【讨论】:

    【解决方案6】:

    根据React Router v4 documentation - Redux Deep Integration session

    需要深度集成:

    “能够通过调度操作进行导航”

    但是,他们推荐这种方法作为“深度集成”的替代方案:

    “您可以将提供的历史对象传递给将组件路由到您的操作并在那里导航,而不是调度操作来导航。”

    所以你可以用 withRouter 高阶组件来包装你的组件:

    export default withRouter(connect(null, { actionCreatorName })(ReactComponent));

    这会将历史 API 传递给 props。因此,您可以调用将历史作为参数传递的动作创建者。例如,在您的 ReactComponent 内部:

    onClick={() => {
      this.props.actionCreatorName(
        this.props.history,
        otherParams
      );
    }}
    

    然后,在你的 actions/index.js 中:

    export function actionCreatorName(history, param) {
      return dispatch => {
        dispatch({
          type: SOME_ACTION,
          payload: param.data
        });
        history.push("/path");
      };
    }
    

    【讨论】:

      【解决方案7】:

      这是我的 hack(这是我的根级文件,其中混合了一点 redux - 虽然我没有使用 react-router-redux):

      const store = configureStore()
      const customHistory = createBrowserHistory({
        basename: config.urlBasename || ''
      })
      
      ReactDOM.render(
        <Provider store={store}>
          <Router history={customHistory}>
            <Route component={({history}) => {
              window.appHistory = history
              return (
                <App />
              )
            }}/>
          </Router>
        </Provider>,
        document.getElementById('root')
      )
      

      然后我可以在任何我想要的地方使用window.appHistory.push()(例如,在我的redux 存储函数/thunks/sagas 等中)我曾希望我可以只使用window.customHistory.push(),但由于某种原因react-router 似乎从未更新即使网址发生了变化。但是这样我就有了 EXACT 实例 react-router 使用。我不喜欢将东西放在全球范围内,这是我会做的少数事情之一。但它比我见过的任何其他替代方案都要好。

      【讨论】:

        【解决方案8】:

        您可以在组件之外使用history 方法。试试下面的方法。

        首先,创建一个history对象,使用the history package

        // src/history.js
        
        import { createBrowserHistory } from 'history';
        
        export default createBrowserHistory();
        

        然后用&lt;Router&gt;包裹它(请注意,你应该使用import { Router }而不是import { BrowserRouter as Router }):

        // src/index.jsx
        
        // ...
        import { Router, Route, Link } from 'react-router-dom';
        import history from './history';
        
        ReactDOM.render(
          <Provider store={store}>
            <Router history={history}>
              <div>
                <ul>
                  <li><Link to="/">Home</Link></li>
                  <li><Link to="/login">Login</Link></li>
                </ul>
                <Route exact path="/" component={HomePage} />
                <Route path="/login" component={LoginPage} />
              </div>
            </Router>
          </Provider>,
          document.getElementById('root'),
        );
        

        从任何地方更改您当前的位置,例如:

        // src/actions/userActionCreators.js
        
        // ...
        import history from '../history';
        
        export function login(credentials) {
          return function (dispatch) {
            return loginRemotely(credentials)
              .then((response) => {
                // ...
                history.push('/');
              });
          };
        }
        

        UPD:您还可以在React Router FAQ 中看到一个略有不同的示例。

        【讨论】:

        • 我尝试完全按照@OlegBelostotsky 所说的去做,但是在history.push('some path') 之后,URL 发生了变化,但页面没有变化。我必须在代码的某些部分中将window.location.reload() 放在它之后,以使其正常工作。但是,在一种情况下,我必须保留 redux 状态树,并且重新加载会破坏它。还有其他解决方案吗?
        • @idunno 尝试使用withRouter 高阶组件。
        • 这给了我一个错误声明:createBrowserHistory 不是一个函数。我能做什么?
        • 很抱歉投了反对票 :)。虽然这也应该有效,但正确的处理方法是 Chris 的回答:stackoverflow.com/a/42716055/491075
        • 确保您使用正确的历史版本,如docs 所示。在将历史 v5 与反应路由器 v5 一起使用时,我遇到了与 @sdabrutas 类似的问题(url 推送到历史但页面没有改变)。将历史记录降级到 v4 完全解决了这个问题。
        【解决方案9】:

        讨厌的问题,花了我很多时间,但最终,我是这样解决的:

        withRouter 包裹您的容器,并在mapDispatchToProps 函数中将历史记录传递给您的操作。在行动中使用 history.push('/url') 进行导航。

        行动:

        export function saveData(history, data) {
          fetch.post('/save', data)
             .then((response) => {
               ...
               history.push('/url');
             })
        };
        

        容器:

        import { withRouter } from 'react-router-dom';
        ...
        const mapDispatchToProps = (dispatch, ownProps) => {
          return {
            save: (data) => dispatch(saveData(ownProps.history, data))}
        };
        export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Container));
        

        这对 React Router v4.x 有效。

        【讨论】:

        • 谢谢,您的 withRouter 解决方案适用于打字稿,但与之前的 import { createBrowserHistory } from 'history' 相比,它的速度相当慢@ 有什么想法吗?
        【解决方案10】:

        如果它对其他人有价值,我会提供另一种解决方案。

        我有一个 history.js 文件,其中包含以下内容:

        import createHistory from 'history/createBrowserHistory'
        const history = createHistory()
        history.pushLater = (...args) => setImmediate(() => history.push(...args))
        export default history
        

        接下来,在我定义路由器的根上,我使用以下内容:

        import history from '../history'
        import { Provider } from 'react-redux'
        import { Router, Route, Switch } from 'react-router-dom'
        
        export default class Root extends React.Component {
          render() {
            return (
             <Provider store={store}>
              <Router history={history}>
               <Switch>
                ...
               </Switch>
              </Router>
             </Provider>
            )
           }
          }
        

        最后,在我的actions.js 上,我导入 History 并使用 pushLater

        import history from './history'
        export const login = createAction(
        ...
        history.pushLater({ pathname: PATH_REDIRECT_LOGIN })
        ...)
        

        这样,我可以在 API 调用后推送新操作。

        希望对你有帮助!

        【讨论】:

          【解决方案11】:

          我可以通过使用bind() 来实现这一点。我想单击index.jsx 中的一个按钮,将一些数据发布到服务器,评估响应,然后重定向到success.jsx。以下是我的解决方法...

          index.jsx:

          import React, { Component } from "react"
          import { postData } from "../../scripts/request"
          
          class Main extends Component {
              constructor(props) {
                  super(props)
                  this.handleClick = this.handleClick.bind(this)
                  this.postData = postData.bind(this)
              }
          
              handleClick() {
                  const data = {
                      "first_name": "Test",
                      "last_name": "Guy",
                      "email": "test@test.com"
                  }
          
                  this.postData("person", data)
              }
          
              render() {
                  return (
                      <div className="Main">
                          <button onClick={this.handleClick}>Test Post</button>
                      </div>
                  )
              }
          }
          
          export default Main
          

          request.js:

          import { post } from "./fetch"
          
          export const postData = function(url, data) {
              // post is a fetch() in another script...
              post(url, data)
                  .then((result) => {
                      if (result.status === "ok") {
                          this.props.history.push("/success")
                      }
                  })
          }
          

          success.jsx:

          import React from "react"
          
          const Success = () => {
              return (
                  <div className="Success">
                      Hey cool, got it.
                  </div>
              )
          }
          
          export default Success
          

          所以通过将this 绑定到index.jsx 中的postData,我能够访问request.js 中的this.props.history...然后我可以在不同的组件中重用这个函数,只要确保我记得在constructor() 中包含this.postData = postData.bind(this)

          【讨论】:

            【解决方案12】:

            你可以像我这样使用它来登录和许多不同的事情

            class Login extends Component {
              constructor(props){
                super(props);
                this.login=this.login.bind(this)
              }
            
            
              login(){
            this.props.history.push('/dashboard');
              }
            
            
            render() {
            
                return (
            
               <div>
                <button onClick={this.login}>login</login>
                </div>
            
            )
            

            【讨论】:

              【解决方案13】:
              /*Step 1*/
              myFunction(){  this.props.history.push("/home"); }
              /**/
               <button onClick={()=>this.myFunction()} className={'btn btn-primary'}>Go 
               Home</button>
              

              【讨论】:

              • 不需要任何进口!
              • 虽然此代码可能会回答问题,但提供有关此代码为何和/或如何回答问题的额外上下文可提高其长期价值。
              【解决方案14】:

              使用回调。它对我有用!

              export function addProduct(props, callback) {
                return dispatch =>
                  axios.post(`${ROOT_URL}/cart`, props, config)
                  .then(response => {
                  dispatch({ type: types.AUTH_USER });
                  localStorage.setItem('token', response.data.token);
                  callback();
                });
              }
              

              在组件中,你只需要添加回调

              this.props.addProduct(props, () => this.props.history.push('/cart'))
              

              【讨论】:

                【解决方案15】:

                第一步将您的应用包装在路由器中

                import { BrowserRouter as Router } from "react-router-dom";
                ReactDOM.render(<Router><App /></Router>, document.getElementById('root'));
                

                现在我的整个应用程序都可以访问 BrowserRouter。第二步,我导入 Route,然后传递这些道具。可能在您的一个主要文件中。

                import { Route } from "react-router-dom";
                
                //lots of code here
                
                //somewhere in my render function
                
                    <Route
                      exact
                      path="/" //put what your file path is here
                      render={props => (
                      <div>
                        <NameOfComponent
                          {...props} //this will pass down your match, history, location objects
                        />
                      </div>
                      )}
                    />
                

                现在,如果我在我的组件 js 文件中运行 console.log(this.props),我应该得到如下所示的内容

                {match: {…}, location: {…}, history: {…}, //other stuff }
                

                第 2 步我可以访问历史对象来更改我的位置

                //lots of code here relating to my whatever request I just ran delete, put so on
                
                this.props.history.push("/") // then put in whatever url you want to go to
                

                另外我只是一个编程训练营的学生,所以我不是专家,但我知道你也可以使用

                window.location = "/" //wherever you want to go
                

                如果我错了,请纠正我,但是当我测试它时,它重新加载了整个页面,我认为这破坏了使用 React 的全部意义。

                【讨论】:

                  【解决方案16】:

                  React 路由器 V4 现在允许使用 history 属性,如下所示:

                  this.props.history.push("/dummy",value)
                  

                  然后可以在任何位置属性可用的地方访问该值 state:{value} 不是组件状态。

                  【讨论】:

                  • 这并不能回答所提出的问题,即如何访问组件的 history.push OUTSIDE。在组件之外使用 this.props.history 不是一个选项。
                  【解决方案17】:

                  React Router 4 中最简单的方法是使用

                  this.props.history.push('/new/url');
                  

                  但要使用此方法,您的现有组件应该可以访问history 对象。我们可以通过

                  1. 如果您的组件直接链接到Route,那么您的组件已经可以访问history 对象。

                    例如:

                    <Route path="/profile" component={ViewProfile}/>
                    

                    这里ViewProfile 可以访问history

                  2. 如果没有直接连接到Route

                    例如:

                    <Route path="/users" render={() => <ViewUsers/>}
                    

                    然后我们必须使用withRouter,这是一个高阶函数来扭曲现有组件。

                    内部 ViewUsers组件

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

                    • export default withRouter(ViewUsers);

                    现在就是这样,您的ViewUsers 组件可以访问history 对象。

                  更新

                  2- 在这种情况下,将所有路由props 传递给您的组件,然后即使没有HOC,我们也可以从组件访问this.props.history

                  例如:

                  <Route path="/users" render={props => <ViewUsers {...props} />}
                  

                  【讨论】:

                  • 太棒了!您的第二种方法也对我有用,因为我的组件(需要访问 this.props.history)来自 HOC,这意味着它没有直接链接到 Route,正如您所解释的那样。
                  • 请注意,当您使用history.push 时,第二个参数是状态(请参阅reactrouter.com/web/api/history)。就我而言,我在更新状态的操作之后立即执行了history.push('/same/route/I/am/currently/on', this.state)。这会导致新状态被添加到历史堆栈中。然后在compoenntDidMount() 中检查this.props.location.state 是否已定义,如果是,则在我返回组件时调用this.setState(this.props.location.state) 以恢复状态。
                  • 这并没有回答原始问题如何在组件外使用历史记录
                  【解决方案18】:

                  所以我这样做的方式是: - 我没有使用history.push 进行重定向,而是使用来自react-router-domRedirect 组件 使用此组件时,您只需传递push=true,其余部分由它处理

                  import * as React from 'react';
                  import { Redirect } from 'react-router-dom';
                  class Example extends React.Component {
                    componentDidMount() {
                      this.setState({
                        redirectTo: '/test/path'
                      });
                    }
                  
                    render() {
                      const { redirectTo } = this.state;
                  
                      return <Redirect to={{pathname: redirectTo}} push={true}/>
                    }
                  }
                  

                  【讨论】:

                  • 这是正确的,不会破坏反应渲染周期
                  【解决方案19】:

                  使用自己的browserHistory 创建自定义Router

                  import React from 'react';
                  import { Router } from 'react-router-dom';
                  import { createBrowserHistory } from 'history';
                  
                  export const history = createBrowserHistory();
                  
                  const ExtBrowserRouter = ({children}) => (
                    <Router history={history} >
                    { children }
                    </Router>
                  );
                  
                  export default ExtBrowserRouter
                  

                  接下来,在您定义 Router 的根上,使用以下命令:

                  import React from 'react';       
                  import { /*BrowserRouter,*/ Route, Switch, Redirect } from 'react-router-dom';
                  
                  //Use 'ExtBrowserRouter' instead of 'BrowserRouter'
                  import ExtBrowserRouter from './ExtBrowserRouter'; 
                  ...
                  
                  export default class Root extends React.Component {
                    render() {
                      return (
                        <Provider store={store}>
                          <ExtBrowserRouter>
                            <Switch>
                              ...
                              <Route path="/login" component={Login}  />
                              ...
                            </Switch>
                          </ExtBrowserRouter>
                        </Provider>
                      )
                    }
                  }
                  

                  最后,在需要的地方导入history并使用:

                  import { history } from '../routers/ExtBrowserRouter';
                  ...
                  
                  export function logout(){
                    clearTokens();      
                    history.push('/login'); //WORKS AS EXPECTED!
                    return Promise.reject('Refresh token has expired');
                  }
                  

                  【讨论】:

                    【解决方案20】:

                    现在有了 react-router v5,你可以像这样使用 useHistory 钩子:

                    import { useHistory } from "react-router-dom";
                    
                    function HomeButton() {
                      let history = useHistory();
                    
                      function handleClick() {
                        history.push("/home");
                      }
                    
                      return (
                        <button type="button" onClick={handleClick}>
                          Go home
                        </button>
                      );
                    }
                    

                    阅读更多:https://reacttraining.com/react-router/web/api/Hooks/usehistory

                    【讨论】:

                    • 我需要什么特定的方法来设置它,我调用了以下let history = useHistory();,但是收到Object is not callable 错误,当我尝试查看useHistory 是什么console.log(useHistory) 时出现了作为未定义。使用"react-router-dom": "^5.0.1"
                    • @steff_bdh 您需要在您的 package.json 文件中将其更新为 "react-router-dom": "^5.0.1" 并运行 'npm install'
                    • 不错,但不能在 redux 操作类中使用钩子,因为它们不是 React 组件/函数
                    • 如何在使用(异步)登录时使用它进行重定向。这是问题=> stackoverflow.com/questions/62154408/…
                    • 引用 React 的话:“钩子只能在 函数组件的主体内部调用。”
                    【解决方案21】:

                    如果你想在将函数作为值传递给组件的 prop 时使用历史记录,使用 react-router 4 你可以简单地解构 @987654322 的 render 属性中的 history prop @Component 然后使用history.push()

                        <Route path='/create' render={({history}) => (
                          <YourComponent
                            YourProp={() => {
                              this.YourClassMethod()
                              history.push('/')
                            }}>
                          </YourComponent>
                        )} />
                    

                    注意:为此,您应该将 React Router 的 BrowserRouter 组件包裹在您的根组件周围(例如,它可能在 index.js 中)

                    【讨论】:

                      【解决方案22】:

                      我在同一个话题上苦苦挣扎。 我正在使用 react-router-dom 5、Redux 4 和 BrowserRouter。 我更喜欢基于函数的组件和钩子。

                      你像这样定义你的组件

                      import { useHistory } from "react-router-dom";
                      import { useDispatch } from "react-redux";
                      
                      const Component = () => {
                        ...
                        const history = useHistory();
                        dispatch(myActionCreator(otherValues, history));
                      };
                      
                      

                      你的动作创建者正在关注

                      const myActionCreator = (otherValues, history) => async (dispatch) => {
                        ...
                        history.push("/path");
                      }
                      

                      如果不需要异步,您当然可以使用更简单的操作创建器

                      【讨论】:

                        【解决方案23】:

                        小心不要将react-router@5.2.0react-router-dom@5.2.0history@5.0.0 一起使用。 URL 将在 history.push 或任何其他推送到历史记录指令之后更新,但导航不适用于 react-router。使用npm install history@4.10.1 更改历史版本。见React router not working after upgrading to v 5

                        我认为这个问题是在推动历史发生时发生的。例如,使用 &lt;NavLink to="/apps"&gt; 在使用 &lt;RouterContext.Consumer&gt; 的 NavLink.js 中遇到问题。当推送到历史记录时,context.location 正在更改为具有操作和位置属性的对象。所以currentLocation.pathname 为空来匹配路径。

                        【讨论】:

                          【解决方案24】:

                          由于我们已经在 react 路由器 5 中包含了历史记录,我们可以通过参考访问相同的历史记录

                          import React from 'react';
                          import { BrowserRouter, Switch, Route } from 'react-router-dom';
                          
                          function App() {
                             const routerRef = React.useRef();
                             const onProductNav = () => {
                                 const history = routerRef.current.history;
                                 history.push("product");
                             }
                          return (
                              <BrowserRouter ref={routerRef}>
                                  <Switch>
                                      <Route path="/product">
                                          <ProductComponent />
                                      </Route>
                                      <Route path="/">
                                          <HomeComponent />
                                      </Route>
                                  </Switch>
                              </BrowserRouter>
                          )
                          }
                          

                          【讨论】:

                          • 谢谢,效果很好。
                          【解决方案25】:

                          在 v6 中,应重写此应用以使用导航 API。大多数情况下,这意味着将 useHistory 更改为 useNavigate 并更改 history.push 或 history.replace 调用站点。

                          // This is a React Router v6 app
                          import { useNavigate } from "react-router-dom";
                          
                          function App() {
                            let navigate = useNavigate();
                            function handleClick() {
                              navigate("/home");
                            }
                            return (
                              <div>
                                <button onClick={handleClick}>go home</button>
                              </div>
                            );
                          }
                          

                          know more

                          【讨论】:

                            猜你喜欢
                            • 2020-10-16
                            • 2022-07-18
                            • 2017-12-08
                            • 2017-12-14
                            • 2017-07-29
                            相关资源
                            最近更新 更多