I have the following code within a component where I am using a cookie value to decide which component or div block to show.
This works eventually as expected. But there is a short while where it seems like the cookie value is not checked yet.
During this period, I keep entering the else
block first. After a couple of seconds, I enter the if
block correctly.
But why? That Cookies.get
is an async call. But I am calling it inside useEffect
and using await.
Could I please know how I could modify this so that if the cookie is existing, I will never enter the else block?
import React from 'react';
import Cookies from 'js-cookie';
const Sample = () => {
const [cookie, setCookie] = React.useState(false);
const hasCookie = async () => !!Cookies.get('my-cookie');
React.useEffect(() => {
const myCookie = async () => await hasCookie();
myCookie().then((result) => setCookie(result));
}, []);
const component = () => {
if (cookie) {
console.log(`YES there is a cookie: ${cookie}`);
return <div>
Yup the cookie exists
</div>;
} else {
console.log(`NO no cookie: ${cookie}`);
return <div>
Nope no cookie
</div>;
}
};
return component();
};
export default Sample;
For reference the following is the console log where it prints false for while before turning to true.
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:20 NO no cookie: false
Sample.jsx:15 YES there is a cookie: true
Sample.jsx:15 YES there is a cookie: true
Sample.jsx:15 YES there is a cookie: true
....
CodePudding user response:
Well first of all there is something that may be a future problem:
Because Cookies.get('my-cookie')
returns a Promise, it's an object. Using !!
on objects always returns true (objects are truthy).
So hasCookie
should always return true?
To make it properly test if it exists you should await
the Promise until it resolves, then use !!
on the resolved value:
!!(await Cookies.get('my-cookie'));
To answer your question, the most common way is a state that tracks if something is loading:
const [loading, setLoading] = useState(true);
When it is loading, you return something else:
if (loading) return null; // if you don't want to render anything
Otherwise you can continue as normal.
When you set the cookie, also make sure to set loading to false:
setCookie(result);
setLoading(false);