无法使用react-router 4

时间:2017-04-21 12:29:36

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

我已经阅读了很多关于这个主题的文档和SOF问题我使用了很多方法来完成这个但是没有一个方法能够以我需要的方式工作。我想我错过了一些重要的东西。很难在我使用的每种导航方法上提供详细而相关的代码,我会尝试一下。

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

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

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

      <div id='game-container' width="1126" height="634">
        <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打包的App组件

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");
浏览器中的

url正在更改,但可视页面没有。

方法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' width="1126" height="634">
        <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" });

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

1 个答案:

答案 0 :(得分:2)

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

因此,如果您呈现<Redirect to={{ pathname: this.state.redirectTo }}/>,它只会在第一次呈现时重定向,但如果您使用以下内容更新状态,则不会重定向:

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