React authentication flickering issue in changing route

Multi tool use
Multi tool use


React authentication flickering issue in changing route



I'm building several application in react, the last one is a admin panel so my react app must have authentication, absolutely all of my products used Server Side Rendering.


react


react


Server Side Rendering



For The last case, back-end team use pass me Token for handling authorization, they technologies are Java, Spring, Redis and etc base.


Token


Java


Spring


Redis



When I send username and password to their server, If the information be correct, they send for me token and something else, I store it in localStorage and change the root state of react application as login, because of this change app use a different routing.


username


password


token


localStorage


state


react


routing



Everything looks good but what happen when I refresh the page? here the issue will happen, the login state is false so app goes to login page, in componentDidMount I read the localStorage and find out Oah! I got the token before and the app is logged in, so change the login state to true.


login


state


false


componentDidMount


localStorage


login


state


true



HERE, flickering happen, and I don't know how I can prevent this bad event.



My root state is like below:


state


class App extends Component {

constructor() {
super();

this.state = { //the root state
login: false,
};

};
...



The componentDidMount is like below:


componentDidMount


componentDidMount() {
this.loginStateHandler(!!JSON.parse(localStorage.getItem('accessToken')));
};

loginStateHandler = (login) => {

if (!login) {

localStorage.clear();
}

this.setState({
login,
});
};



And the switching between login route and app route is in render function of root component that name is App, see below code:


render


App


{
this.state.login
? (
<div className={styles['app-wrapper']}>
<div className={styles['app-wrapper__top']}>
<Button classes={{root: this.props.classes.exitButton}} onClick={this.logoutHandler}>
exit
</Button>
</div>
<AppRoutes key='appRoutes' fetchManager={this.fetchManager}/>
</div>
)
: (
<LoginRoutes loginHandler={this.loginHandler}/>
)
}



How I can write authentication that prevent this flickering. I want the app decide that the user is logged in or not before first render. is it possible?




3 Answers
3



You could put all that logic right in the constructor instead, so that your login variable in your state will be correct straight away:


constructor


login


class App extends Component {
constructor() {
super();

const login = !!JSON.parse(localStorage.getItem('accessToken');

if (!login) {
localStorage.clear();
}
this.state = { login };
}
}





Does constructor run in server side?
– AmerllicA
Jul 1 at 14:43


constructor





@AmerllicA Yes, the constructor is run on the server if you are using renderToString on the server.
– Tholle
Jul 1 at 14:47


constructor


renderToString





So on the server how code can read localStorage?, it's for browser!
– AmerllicA
Jul 1 at 16:00


localStorage





@AmerllicA You need to change the logic for the server of course, but to avoid flickering the state needs to be set in the constructor.
– Tholle
Jul 1 at 16:02


state


constructor





@AmerllicA If you want to server render and have it change depending on if the user is logged in or not, you have to talk with your backend developers how they know the user is logged in or not. If you can't, you could just render null on the server and just do the rendering in the browser when you know the user is logged in or not from localStorage, to circumvent the flickering.
– Tholle
Jul 1 at 18:00


null



common pattern is to delay rendering until you read user login state from LocalStorage



for example in Redux has Redux persist library that stores redux state so it's kept on page refresh



recently they added HOC for waiting for loading the local state
https://github.com/rt2zz/redux-persist/blob/master/docs/PersistGate.md



you can see that this HOC has option for loading component so it displays that until local state is loaded



I suggest you do the same with some logic for waiting / showing loading until local storage is loaded



I just found a real good way by myself, at first I render null in render function of login component, then put the below code in componentDidMount life cycle method:


render


null


login


componentDidMount


setTimeout(() => {
if (!JSON.parse(localStorage.getItem('loginDetails'))) {
this.setState({
renderDOM: true,
})
}
}, 0);



This means, if the app is not login render the login component, because of using setTimeout, the condition disappear from call stack and then after wiping stack the condition goes to stack so for this awesome delay when the app is logged in, you never see login page flickering.


login


setTimeout


call stack


stack


stack



But this way has something, maybe I guess it can be a SEO issue, when somebody is logged-in and directly call some page like website.com/users-list-page/ then at first app goes to login component and the login component render null then app read thelocalStorageand find out oOH!, I'm logged-in sosetStatetologintrue, then app goes tousers-list-pagewith related component, but _remember_, theloginpage is rendered in server asnulland because of the app was logged-in, the call back function ofsetTimeoutdoesn't run anything, so when theusers-list-pageappear pressing <kbd>Ctrl</kbd>+<kbd>U</kbd> to show pageHTML` sources, you see nothing in


SEO


website.com/users-list-page/


login


component


null then app read the


and find out oOH!, I'm logged-in so


to



, then app goes to


with related component, but _remember_, the


page is rendered in server as


and because of the app was logged-in, the call back function of


doesn't run anything, so when the


appear pressing <kbd>Ctrl</kbd>+<kbd>U</kbd> to show page


<div id="root"></div>



This maybe cause to SEO issues. I don't know, maybe someone has an idea?


SEO



Maybe there is an other way to avoid flickering and then render the users-list-page DOM from server. I've no idea yet. ☹️


users-list-page


DOM






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

hwMz fps AKJK 4wOvpZ96ZBzqK
yji94iDr Pbn jVpBxAs79bplheAGJzzV1ltXjO,ZP,Z7MPePjfgJvKOQqYlWAOSYyCjeLcvMr

Popular posts from this blog

Rothschild family

Cinema of Italy