meteor-react-boilerplate icon indicating copy to clipboard operation
meteor-react-boilerplate copied to clipboard

I can't seem to redirect using rr4

Open q3e opened this issue 7 years ago • 1 comments

I posted this question on SO after watching your VIDEOS series in which you were using FlowRouter with react router. However, this repo migrated to rr4 and I am trying to get a redirect onSubmit but it doesnt seem to work. Route redirects are working fine, as in user cannot access register/login when already loggedin, but when on the login page, user is not redirected. There isnt a FlowRouter.go() equivalent in rr4 and I am forced to put the login check logic within the component and force rerender with react's this.forceUpdate() - which doesn work for me here is the SO question

q3e avatar Apr 22 '17 07:04 q3e

Hi @nfatah ,

I'm not sure who's video that is but isn't mine so i'm not sure what they did. However, I can let you know how I handle redirects with React Router V4.

Note, this was used in an early release of their V4 so it could be broken, but I doubt it.

RR doesn't have a .go function but they let you access transitionTo via context that does the same thing. However I find that to be such a hassle every time you want to redirect. More importantly I needed to redirect in an action function outside of the UI.

I accessed the function with context and exposed it globally like this:

window._tt  = this.context.router.transitionTo;

However, there is a catch. This typically is accessed on the root of the page so if you put it on the 'home' page and the user never visits there, then it won't be available globally. To solve this I made a wrapper component called <ExposeRouter> in my layout and wrapped it around the 'routes' like this:

// expose a transition function so that actions can easily call it without having to use context
const ExposeRouter = React.createClass({
  getInitialState: () => ({
    isExposed: false,
  }),
  contextTypes: {
    router: React.PropTypes.object.isRequired
  },
  componentDidMount() {
    window._tt  = this.context.router.transitionTo;
    // defer rendering UI until context is set to prevent race conditions
    setTimeout(() => this.setState({isExposed: true}), 0);
  },
  render() {
    return this.state.isExposed ? this.props.children : null;
  }
});



const MainLayout = React.createClass({
  render() {
    return (
      <BrowserRouter>
          <ExposeRouter>
              <div>
                <Header />

                <div role="main">
                  <Match exactly pattern="/" component={Home} />
                  <Match exactly pattern="/login" component={Login} />
                  <Miss component={NotFound} />
                </div>
              </div>

          </ExposeRouter>
      </BrowserRouter>
    );
  },
});


export default MainLayout;

and then in another folder I made a module like this to call the global function. This isn't necessary but it encapsulates the functionality I want in case I want to change routers in the future (not uncommon in React land lol):

export const transitionToRoute = (url) => window._tt(url);

AdamBrodzinski avatar Apr 23 '17 01:04 AdamBrodzinski