Reputation: 647
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()
})
}
export default (
<Route component={Root} >
<Route path='/' component={Home} onEnter={Authentication}/>
<Route path='/login' component={Login} onEnter={Authentication}/>
<Route path='/signup' component={Registration} onEnter={Authentication}/>
<Route path='/account/wall' component={Wall}/>
<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??
Upvotes: 0
Views: 1836
Reputation: 3745
I can't write the exact example because everyone's implementation differs, but I am going to right a HelloWrapper component example which wraps any component and if it receive the sayHello prop to true, it render the Hello instead of actual component, you can check the login props and redirect or show login component..in your case.
HoistNonReactStatistics.tsx or jsx ( I use typescript)
const REACT_STATICS = {
childContextTypes: true,
contextTypes: true,
defaultProps: true,
displayName: true,
getDefaultProps: true,
mixins: true,
propTypes: true,
type: true
};
const KNOWN_STATICS = {
name: true,
length: true,
prototype: true,
caller: true,
arguments: true,
arity: true
};
export default function hoistStatics(targetComponent, sourceComponent) {
var keys = Object.getOwnPropertyNames(sourceComponent);
for (var i = 0; i < keys.length; ++i) {
const key = keys[i];
if (!REACT_STATICS[key] && !KNOWN_STATICS[key]) {
try {
targetComponent[key] = sourceComponent[key];
} catch (error) {}
}
}
return targetComponent;
}
write wrapper function which will return wrapped component
import * as React from 'react';
import HoistNonReactStatistics from "./HoistNonReactStatistics"
export function HelloWrapper(){
return function HellowWrapComponent(DecoratedComponent) {
class WrappendComponent extends React.Component<{sayHello?:boolean},{}>{
constructor(props){
super(props);
}
componentWillMount(){
/** do some login check here and redirect if required **/
}
componentWillReceiveProps(nextProps){
/** do some login check here and redirect if required **/
}
render(){
if(this.props.sayHello){
return <div>Hello</div>
}else{
return <DecoratedComponent />
}
}
}
/** if you use redux then also apply the connect method on return component so it get access to required auth reducer data**/
return HoistNonReactStatistics(WrappendComponent,DecoratedComponent);
}
}
export const requireHellow = HelloWrapper();
export default requireHellow(SomeComponent);
now whenever you use this SomeComponent and it has sayHello prop to true it will render Hello otherwise render the actual component
Upvotes: 1
Reputation: 1
<code>function requireAuth(nextState, replace,callback){
var data = {
token: store.getState().student.token,
email: store.getState().student.email}
makeUserRequest('post', data, '/api/auth')
.then((res)=>{
if (!res.data.success) {
replace({ nextPathname: nextState.location.pathname }, nextState.location.query)
}
callback()
})
}
return(
<Router history={browserHistory}>
<Route path='/' component={app}>
<IndexRoute component={login} />
<Route path='home' component={home} />
<Route path='login' component={login} />
<Route path='profile' component={profile} onEnter={requireAuth} />
</Route>
)
Upvotes: 0