Unable to redirect programmatically with reactive router 4

I have read a lot of SOF docs and questions on this subject. I have used many methods for this, but none of them worked the way I needed. I guess I am missing something important. It is difficult to provide detailed and relevant code for every navigation method I have used, I will try.

Here are some introductory images. I had a react-redux application, I need to get the state from the server and redirect to the page according to that state.

A simplified version of the render method of the application class:

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

      

Application component wrapped in BrowserRouter in index.js file

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

      

Method 1.withRouter

For implementation, I added this code:

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

      

and then when I get the session information, I try:

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

      

The url in the browser changes, but the visual page doesn't work.

Method 2.with context router

For this, just added

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

      

and then when I get the session information, I try:

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

      

Same result as in first method (url changed, but no page).

Method 3. Forwarding (found here Programmatic transition with responsive V4 router )

So my render method looks like this:

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

      

And when I want to change the page, I set a new state:

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

      

This method gives strange results. When I set the initial state in the constructor, it is redirected to any page. But when I use this method anywhere in the code, I can see in debug that the render method is called with my new state, but the redirection never happens!

+3


source to share


1 answer


In v4, method 3 should be the correct method (using a component Redirect

). The problem you are having appears Redirect

to be because it only takes effect the first time, but you push Redirect to the top level of your router and it only gets installed once.

So, if you are rendering <Redirect to={{ pathname: this.state.redirectTo }}/>

, it will only redirect the first time it is displayed, but it will not redirect if you update the state using:

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

      

This is why it only worked for you when you set redirectTo

in the constructor but don't redirect afterwards.



Instead, you probably have to use Redirect

in every component / route you want to invoke a redirect, it's not as tedious as it sounds because you can just create your own route component to use instead of the typical component Route

and handle all the redirection logic once per your custom component.

You can find an example here where and Route

are used instead to check if the user is logged in and redirected accordingly: https://github.com/tylermcginnis/react-router-firebase-auth/blob/master/src/components/index. jsPrivateRoute

PublicRoute

Here's how PrivateRoute, which should only be available for login, looks like this:

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

      

+2


source







All Articles