I am using a similar code like this to redirect in my app after users logged in. The code looks like the following:
import React, { Component } from 'react'
import { Redirect } from 'react-router'
export default class LoginForm extends Component {
constructor () {
super();
this.state = {
fireRedirect: false
}
}
submitForm = (e) => {
e.preventDefault()
//if login success
this.setState({ fireRedirect: true })
}
render () {
const { from } = this.props.location.state || '/'
const { fireRedirect } = this.state
return (
<div>
<form onSubmit={this.submitForm}>
<button type="submit">Submit</button>
</form>
{fireRedirect && (
<Redirect to={from || '/home'}/>
)}
</div>
)
}
}
Works fine when a successful login has been triggered. But there is the case, that logged in users enter the login page and should be automatically redirected to the "home" page (or whatever other page).
How can I use the Redirect ponent without rendering the current ponent and without (as far as I understand discouraged) imperative pushing to the history (e.g. in ponentWillMount
)?
I am using a similar code like this to redirect in my app after users logged in. The code looks like the following:
import React, { Component } from 'react'
import { Redirect } from 'react-router'
export default class LoginForm extends Component {
constructor () {
super();
this.state = {
fireRedirect: false
}
}
submitForm = (e) => {
e.preventDefault()
//if login success
this.setState({ fireRedirect: true })
}
render () {
const { from } = this.props.location.state || '/'
const { fireRedirect } = this.state
return (
<div>
<form onSubmit={this.submitForm}>
<button type="submit">Submit</button>
</form>
{fireRedirect && (
<Redirect to={from || '/home'}/>
)}
</div>
)
}
}
Works fine when a successful login has been triggered. But there is the case, that logged in users enter the login page and should be automatically redirected to the "home" page (or whatever other page).
How can I use the Redirect ponent without rendering the current ponent and without (as far as I understand discouraged) imperative pushing to the history (e.g. in ponentWillMount
)?
-
1
You're using wrong approach. Redirect should not be used alone inside ponent. Conversely, you have to place your ponent into
Route
along with Redirect. See example in the official docs. – hindmost Commented Jun 6, 2017 at 13:52 - Thank you, yes my approach was somehow wrong. I now have all my routing and redirecting in my Router defined. – Jankapunkt Commented Jun 6, 2017 at 14:26
2 Answers
Reset to default 13Solution 1
You could use withRouter
HOC to access history via props.
Import withRouter.
import {
withRouter
} from 'react-router-dom';
Then wrap with HOC.
// Example code
export default withRouter(connect(...))(Component)
Now you can access this.props.history
. For example use it with ponentDidMount()
.
ponentDidMount() {
const { history } = this.props;
if (this.props.authenticated) {
history.push('/private-route');
}
}
Solution 2 Much better
Here is example on reacttraining.
Which would perfectly work for you.
But you just need to create LoginRoute
to handle problem you described.
const LoginRoute = ({ ponent: Component, ...rest }) => (
<Route
{...rest} render={props => (
fakeAuth.isAuthenticated ? (
<Redirect to={{
pathname: '/private-route',
state: { from: props.location }
}} />
) : (
<Component {...props} />
)
)} />
);
and inside <Router />
just replace
<Route path="/login" ponent={Login}/>
with
<LoginRoute path="/login" ponent={Login}/>
Now everytime somebody will try to access /login
route as authenticated user, he will be redirected to /private-route
. It's even better solution because it doesn't mount your LoginComponent
if condition isn't met.
Here is another solution which doesn't touch React stuff at all. E.g. if you need to navigate inside redux-saga.
Have file history.js:
import {createBrowserHistory} from 'history';
export default createBrowserHistory();
Somewhere where you define routes, don't use browser router but just general <Router/>
:
import history from 'utils/history';
...
<Router history={history}>
<Route path="/" ponent={App}/>
</Router>
That's it. Now you can use same history import and push new route.
In any part of your app:
import history from 'utils/history';
history.push('/foo');
In saga:
import {call} from 'redux-saga/effects';
import history from 'utils/history';
...
history.push('/foo');
yield call(history.push, '/foo');