I'm working on a personal project and I have trouble with checking if a user is logged in or not so that when they try to go to /login, it'll redirect them to the home page. Currently what my code does is the following:
I can't figure out how to fix the problem with rendering the component with the default state and then suddenly redirects because the state changes. Thanks
Routes.js
const Routes = (props) => {
props.checkIfSignedIn();
return(
<Router>
<Switch>
<Route exact path='/' component={App}/>
<AuthorizedRoute path="/signup" component={SignUp}/>
<AuthorizedRoute path="/signin" component={SignIn}/>
<Route component={InvalidPage}/>
</Switch>
</Router>
);
};
const mapDispatchToProps = (dispatch) => {
return{
checkIfSignedIn: () => dispatch(checkIfSignedIn())
};
};
export default connect(null, mapDispatchToProps)(Routes);
AuthorizedRoute.js
class AuthorizedRoute extends React.Component{
constructor(props){
super(props);
this.state = {
isLoggedIn: false
};
};
render(){
const { component: Component, ...rest } = this.props;
return(
<Route {...rest} render={props => {
if (this.props.isLoggedIn){
console.log(this.state.isLoggedIn);
return <Redirect to="/" />
} else{
return <Component {...props} />
}
}} />
);
}
};
const mapStateToProps = (state) => {
return{
isLoggedIn : state.authentication.isLoggedIn
};
};
export default connect(mapStateToProps, null)(AuthorizedRoute);
authentication.js - action creators
const setSignedInFalse = () => {
return{
type: IS_SIGNED_IN_FALSE
};
};
const setSignedInTrue = () => {
return{
type: IS_SIGNED_IN_TRUE
};
};
const checkIfSignedIn = () => {
return dispatch => {
firebaseApp.auth().onAuthStateChanged(user => {
if (user){
dispatch(setSignedInTrue());
} else{
dispatch(setSignedInFalse());
}
});
};
};
export default checkIfSignedIn;
authentication.js - reducer
const defaultState = {
isLoggedIn: false
};
const authentication = (state = defaultState, action) => {
let authenticationState = null;
switch (action.type){
case IS_SIGNED_IN_FALSE:
authenticationState = {
isLoggedIn: false
};
return authenticationState;
case IS_SIGNED_IN_TRUE:
authenticationState = {
isLoggedIn: true
};
return authenticationState;
default:
return state;
};
};
export default authentication;
Hacky solution (Not sure if this is frowned upon).
I set my Auth reducer's default state, isLoggedIn : null instead of false. Then in my AuthorizedRoute component I now have 3 conditions to render null first and then either the component or redirect.
//AuthorizedRoute Component
if (this.props.isLoggedIn){
return <Redirect to="/" />
} else if (this.props.isLoggedIn === false){
return <Component {...props} />
} else{
return null;
}
Options for preventing re-renders One popular method for preventing re-renders is using Selectors in React Redux, which are functions that subscribe to the Redux store and run whenever an action is dispatched. Selectors use === as a strict quality check, re-rendering the component whenever data is changed.
1. Memoization using useMemo() and UseCallback() Hooks. Memoization enables your code to re-render components only if there's a change in the props. With this technique, developers can avoid unnecessary renderings and reduce the computational load in applications.
OR, we can remove function memoization here, and just wrap ChildComponent in React. memo : MovingComponent will re-render, “children” function will be triggered, but its result will be memoized, so ChildComponent will never re-render.
To get rid of your infinite loop, simply use an empty dependency array like so: const [count, setCount] = useState(0); //only update the value of 'count' when component is first mounted useEffect(() => { setCount((count) => count + 1); }, []); This will tell React to run useEffect on the first render.
What you may do is something like this: (in your auth reducer).
let user = JSON.parse(localStorage.getItem('user'));
const initialState = user ? { isLoggedIn: true } : {};
Also you had to set the localstorage when your user is logging in and remove it when he is logging out.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With