I am building a basic react-login app for educational purposes and to authenticate a route I am using React-router's onEnter prop functionality
import axios from 'axios';
var Authentication = (nextState, replace, callback) => {
axios.get('/api/getuser')
.then((res) => {
if(res.data != '') {
replace('account/wall')
}
callback()
})
.catch((err) => {
callback()
})
}
var Authentication2 = (nextState, replace, callback) => {
axios.get('/api/getuser')
.then((res) => {
if(res.data === '') {
replace('/')
} else {
}
callback()
})
.catch((err) => {
callback()
})
}
export default (
<Route component={Root}>
<Route component={Auth} onEnter={Authentication}>
<Route path='/' component={Home} />
<Route path='/login' component={Login} />
<Route path='/signup' component={Registration} />
</Route>
<Route component={Auth} onEnter={Authentication2}>
<Route path='/account/wall' component={Wall} />
</Route>
<Route path='*' component={Notfound} />
</Route>
);
Everything is working as intended But it is beyond me why the router render the Home component for a blink second and THEN replace the route to /account/wall
when I try /
route after logging in?? Same thing happen if I try /login
or /signup
after logging in., Is there anyway to fix this behavior ??
I already tried to solve this by authenticating the user in componentWillMount method (which is not the react way i guess) by rendering empty <div>
when checking for user but that also renders empty page for a blink second and not the correct way to do it.
So I just want to render /account/wall if user is authenticated without any middleware renders. What can I do??
@outlawshade Those 2 routes which have onEnter={Authentication}
will both render once at the start and for any route, and therefore both Authentication functions will run for any route.
Also you should always supply a path
prop to a route to tell it when it should render
I think what you want to do is something more like this:
export default (
<Route path='/' component={Root}>
<IndexRoute component={Home} onEnter={Authentication} />
<Route path='/login' component={Login} onEnter={Authentication} />
<Route path='/signup' component={Registration} onEnter={Authentication} />
<Route path='/account/wall' component={Wall} onEnter={Authentication2} />
<Route path='*' component={Notfound} />
</Route>
);
This means /
login
and signup
routes will all redirect if the user is logged in, and vice-versa for the account/wall
route.
@alisd23 My routing is working perfectly fine. If you read my question again my problem is not if the routes are getting authenticated or not, but I am seeing these one second flashes of component before it switches to the replace route /account/wall
To check it I have already tried doing this few days ago, But the flash still happens!
<Route component={Root}>
<Route path='/' component={Home} onEnter={Authentication} />
<Route path='/account/wall' component={Wall} />
<Route path='*' component={Notfound} />
</Route>
Someone on Discord pointed out that it may be the cause of async api calls in the onEnter function and explained to me how everything is parallel which can cause the flashes.
So today I tried to get rid of the database stored session and start using json web tokens (JWT) to store user authenticated details BUT the flashes still occur before replacing the route.
In the end a few hours ago I also tried wrapping the Home component in a HOC too see if that works and rendered null or Home based on the condition if the user-token is in the localStorage or not... BUT doing that still displayed (flashed) the home component for a second before the state gets updated using the locally stored token.
Is there any standard way authenticating the routes which does not flash any pre Component when using React Router? That's my question and I hope I will find an answer here ? Thanks
If that does not explained it. This is what I am trying to do.
Start App -> Home renders -> Login renders -> User logs in -> Wall renders -> Now if I manually go to "http://localhost:3000" -> Home renders for half a second -> Wall renders....
Why home is rendering? I'm using JWT stored in react-cookie and loading the cookie in onEnter ????
var Auther = (nextState, replace) => {
let token = cookie.load('user-token', {path:'/'})
console.log('from auther ' + token)
token ? replace('/account/wall') : null;
}
export default (
<Route path='/' component={Root}>
<IndexRoute component={Home} onEnter={Auther} />
<Route path='/account/wall' component={Wall} />
<Route path='*' component={Notfound} />
</Route>
);
Just found a solution.. and it looks beautiful <3 <3 OMG IAM SO HAPPY
@outlawshade -- Could you possibly share the solution you came up with?
my solution in React Router 3
class RoutePrivate extends Route {
render() {
function userIsAuth() {
const userData = localStorage.getItem('jwt-user-data');
return userData;
}
if (userIsAuth()) {
return (
<Route path={this.props.path} component={this.props.component} />
);
}
return (
<Redirect
to={{
pathname: '/home',
}}
/>
);
}
}
& using:
<RoutePrivate path="/company" component={Company} />
Most helpful comment
@outlawshade -- Could you possibly share the solution you came up with?