无法使用 react-router 4 以编程方式重定向

Posted

技术标签:

【中文标题】无法使用 react-router 4 以编程方式重定向【英文标题】:Unable to redirect programmatically with react-router 4 【发布时间】:2017-09-18 11:02:51 【问题描述】:

我已经阅读了很多关于这个主题的文档和 SOF 问题,我使用了很多方法来做到这一点,但它们都没有以我需要的方式起作用。我想我错过了一些重要的东西。我使用的每一种导航方式都很难提供详细相关的代码,我试试看。

这里有一些介绍性信息。我有 react-redux 应用程序,我需要从服务器获取状态并根据此状态重定向到页面。

我的 App 类渲染方法的简化版:

 render() 
    console.log("App.render");
    console.log(this.state);
    return (

      <div id='game-container'  >
        <Router>
        <div>
          <Route exact path="/" component=Page1/>
          <Route path="/bets" component=Page2/>
          <Route path="/games" component=Page3/>
          <Route path="/newpage" component=Page4/>
          <Route path="/info" component= Info />
        </div>
        </Router>
        <Overlay/>
      </div>
    );
  
 

在 index.js 文件中用 BrowserRouter 封装的应用组件

ReactDOM.render(
  <Provider store=myStore>
    <BrowserRouter>
      <App assets= assets  locale= qs['locale'] token= qs['token'] sounds= sounds  />
    </BrowserRouter>
  </Provider>
  , document.querySelector('.game-wrapper'));

方法1.withRouter

为了实现,我添加了以下代码:

  App.propTypes = 
      history: React.PropTypes.shape(
      push: React.PropTypes.func.isRequired,
      ).isRequired,
      location: React.PropTypes.object.isRequired,
    ;


function mapStateToProps(state) 
    console.log("app#mapStateToProps");
    console.log(state.session);
    return  session:  state.session 


function mapDispatchToProps(dispatch) 
    return bindActionCreators( fetchInitialSession , dispatch);


export default withRouter(connect(mapStateToProps,  fetchInitialSession )(App));

然后当我获取会话信息时,我会尝试:

 this.props.history.push("/newpage");

浏览器中的网址正在更改,但可视页面没有。

方法 2. 使用上下文路由器

为此刚刚添加

App.contextTypes = 
  router: React.PropTypes.object
;

然后当我获取会话信息时,我会尝试:

 this.context.router.history.push("/newpage");

与第一种方法的结果相同(网址已更改,但页面未更改)。

方法 3. 重定向(在此处找到 Programmatically navigate using react router V4)

所以我的渲染方法是这样的:

render() 
    console.log("App.render");
    console.log(this.state);
    return (

      <div id='game-container'  >
        <Router>
        <div>
      <Redirect to= pathname: this.state.redirectTo />
          <Route exact path="/" component=Page1/>
          <Route path="/bets" component=Page2/>
          <Route path="/games" component=Page3/>
          <Route path="/newpage" component=Page4/>
          <Route path="/info" component= Info />
        </div>
        </Router>
        <Overlay/>
      </div>
    );
  
 

当我想更改页面时,我设置了新状态:

this.setState( redirectTo: "/newpage" );

这种方法给出了奇怪的结果。当我在构造函数中设置初始状态时,它会重定向到任何页面。但是当我在代码中的任何地方使用此方法时,我在调试中看到使用我的新状态调用的渲染方法,但重定向永远不会发生!

【问题讨论】:

当您尝试设置状态时,组件已经挂载。为什么不使用history.push 而不是更改状态? 你读过我的 1 和 2 方法吗? 我们从页面路径开始。您正试图通过/newpage 路径打开某些东西,但您没有在任何地方指定它。你在哪里处理它? 对不起,我在这里发布代码时做了一些调整,指定了/newpage,编辑了我的问题 您发布的代码看起来根本不起作用。你的App 组件中的&lt;Router&gt; 是从哪里来的,因为你的index.js 中已经有&lt;BrowserRouter&gt;,这不是冗余吗?我建议用完整的代码制作一个更简单的示例,包括您的 require 语句,这样我们就可以在最后重现以进行调试。 【参考方案1】:

在 v4 中,方法 3 应该是正确的方法(使用 Redirect 组件)。您遇到的问题似乎是因为Redirect 仅在第一次挂载时生效,但您将 Redirect 放在路由器的顶层并且它只挂载一次。

因此,如果您渲染&lt;Redirect to= pathname: this.state.redirectTo /&gt;,它只会在第一次渲染时重定向,但如果您使用以下方式更新状态,它将不会重定向:

this.setState( redirectTo: "/newpage" );

这就是为什么它仅在您在构造函数中设置 redirectTo 时才对您有效,但之后没有再次重定向。

相反,您可能不得不在要触发重定向的每个组件/路由中使用Redirect,但这并不像听起来那么乏味,因为您可以创建一个自定义路由组件来使用而不是典型的Route 组件并在您的自定义组件中处理一次所有重定向逻辑。

您可以在此处找到一个示例,其中使用PrivateRoutePublicRoute 而不是普通的Route 来检查用户是否已登录并相应地重定向: https://github.com/tylermcginnis/react-router-firebase-auth/blob/master/src/components/index.js

只有登录用户才能访问的 PrivateRoute 如下所示:

function PrivateRoute (component: Component, authed, ...rest) 
  return (
    <Route
      ...rest
      render=(props) => authed === true
        ? <Component ...props />
        : <Redirect to=pathname: '/login', state: from: props.location />
    />
  )

【讨论】:

以上是关于无法使用 react-router 4 以编程方式重定向的主要内容,如果未能解决你的问题,请参考以下文章

在 React-Router v4 中以编程方式导航

Uncaught TypeError: (0 , _reactRouter.withRouter) 在 react-router 2.4.0 中以编程方式导航路由时不是一个函数

在 react-router V4 中,如何以编程方式设置查询字符串参数?

react-router v4:以编程方式触发重定向(无需渲染 <Redirect />)

在 React-Router V4 中以编程方式设置路由参数最终会出现“找不到页面”

React JS:以编程方式使用 React-Router 发送道具 [重复]