react router - Redirection after login

后端 未结 7 2186
天命终不由人
天命终不由人 2021-01-30 14:22

Could you please help me in understanding the redirection mechanism I could use with latest version of react router ( v1.1.0 ) . I would like to redirect to a

相关标签:
7条回答
  • 2021-01-30 14:33

    onEnter no longer exists on react-router-4, You can make use of <Route render={ ... } /> to achieve the same functionality.

    Here is an example of the same.

    <React.Fragment>
        <Switch>
          <Route path="/dashboard" render={() => (isAuth() ? <Redirect to="/login" /> : <DashboardRoutes />)} />
          <Route path="/login" component={Login} />
        </Switch>
    </React.Fragment>
    

    isAuth() in my case is a function that basically check whether we have the auth token or not and returns true/false based on that.

    function isLoggedIn() {
      if (!localStorage.getItem('token')) {
        return true;
      }
      return false;
    }
    
    0 讨论(0)
  • 2021-01-30 14:35

    As @JohnSz mentions I too had issues with using withRouter. Instead I did it as instructed here: https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#programmatic-navigation

    const RouteComponent = React.createClass({
      contextTypes: {
        router: React.PropTypes.object.isRequired
      },
      someHandler() {
        this.context.router.push(...)
      }
    })
    

    Basically:

    1. Define contextType
    2. Use this.context.router.push(...)

    Cheers.

    0 讨论(0)
  • 2021-01-30 14:37

    @terranmoccasin 's answer is correct. However there is a common need very few examples address.

    Let's say you need to secure several routes (dashboard1, dashboard2, ...). How do you redirect back to the original page once you log in successfully? In other words, what do you do with {nextPathname: nextState.location.pathname}?

    Here's what I do in ./containers/LoginContainer.js:

    import { push } from 'react-router-redux';
    const mapStateToProps = (state) => ({
      nextPathname: state.routing.locationBeforeTransitions.state.nextPathname,
    });
    const mapDispatchToProps = (dispatch) => ({
      changeLocationOnSignIn: (nextPathname) => {
        dispatch(push(nextPathname));
      },
    });
    

    and in ./components/Login.js

    componentWillReceiveProps(nextProps) {
      // user signed in or signed up, assuming redux. you may use this elsewhere.
      if (nextProps.user.status === 'authenticated' && nextProps.user.user &&
         !nextProps.user.error) {
           this.props.changeLocationOnSignIn(this.props.nextPathname);
      }
    

    React-router 2.4.0 (April 2016) introduced withRouter which creates a HOC. However it wraps React.createClass, not a JS class. I haven't been able to get it working with redux-form, etc. Besides I think the above code is easier to comprehend.

    0 讨论(0)
  • 2021-01-30 14:41

    Wanted to update this thread because I spent a good amount of time digging around on this. In React Router 2.0.x, replaceState is deprecated in favor of replace. See here for details: https://github.com/ReactTraining/react-router/blob/v2.0.0/upgrade-guides/v2.0.0.md#link-to-onenter-and-isactive-use-location-descriptors

    The correct way to do this would be something like this:

    function requireAuth(nextState, replace) {
      if (!userExists()) {
        replace({
          pathname: '/signin',
          state: { nextPathname: nextState.location.pathname }
        })
      }
    }
    
    export const renderRoutes = () => (
      <Router history={browserHistory}>
          <Route path="protectedRoute" component={Protected} onEnter={requireAuth} />
          <Route path="signin" component={SignIn} />
        </Route>
      </Router>
    );
    

    Then, in the SignIn component, you can redirect after a successful sign in like this:

    signInFunction({params}, (err, res) => {
      // Now in the sign in callback
      if (err)
        alert("Please try again")
      else {
        const location = this.props.location
        if (location.state && location.state.nextPathname) {
          browserHistory.push(location.state.nextPathname)
        } else {
          browserHistory.push('/')
        }
      }
    })
    
    0 讨论(0)
  • 2021-01-30 14:41

    i want just share the actual answer at 2020 year. The main way for storing previous location in state is the same. But onEnter was removed from library. Now we can use AuthRoute as in the documentation:

    <AuthRoute exact path="/food">
      <Food />
    </AuthRoute>
    <Route exact path="/login">
      <Login />
    </Route>
    
    const AuthRoute = ({ children, isAuthorized, ...rest }) => {
      const loginLink = usePrepareLink({
        to: "/login",
        isRelativePath: true
      });
    
      return (
        <Route {...rest} render={({ location }) =>
          isAuthorized ? (
            children
          ) : (
            <Redirect to={{
              ...loginLink,
              state: { from: location }
            }} />
          )
        } />
      );
    };
    

    and we can use the state to restore previouse URL after login

    const onSignIn = useCallback(() => {
      setIsAuthorized(value);
      const link = (state && state.from) || "/restore-prevented-route";
      history.replace(link);
    }, [setIsAuthorized, value, history, state]);
    

    The details you can find here (or RU)

    0 讨论(0)
  • 2021-01-30 14:54

    You can register "hooks" on your routes that get triggered when you enter and leave the routes. Check out the documentation for onEnter and onLeave hooks.

    There is also an example of requiring auth on a route and redirecting to a different path if the user is not logged in.

    Here's a snippet taken from the require auth example within app.js:

    function requireAuth(nextState, replaceState) {
      if (!auth.loggedIn())
        replaceState({ nextPathname: nextState.location.pathname }, '/login')
    }
    
    // And from the route configuration, use the requireAuth function in onEnter...
    <Router history={history}>
      <Route path="/" component={App}>
        <Route path="login" component={Login} />
        <Route path="logout" component={Logout} />
        <Route path="about" component={About} />
        <Route path="dashboard" component={Dashboard} onEnter={requireAuth} />
      </Route>
    </Router>
    

    The nextState and replaceState arguments are objects from rackt/history and get injected into the method you pass into onEnter.

    0 讨论(0)
提交回复
热议问题