I have a simple language selector (en, cs) in my React app using i18next. The change of the language (applying all the translations and re-rendering the app) takes around 2 seconds.
In the meantime, I want to display a loader, but that doesn't seem to work as expected.
I have two scenarios. The first one does not display Loader
:
const [isLoading, setIsLoading] = useState(false)
const [language, setLanguage] = useState(userPreferences.lang);
const handleChangeLanguage = (lang) => {
setIsLoading(true);
setLanguage(lang);
}
useEffect(() => {
i18n.changeLanguage(language).then(() => setIsLoading(false) );
},[language])
return (
<>
{isLoading ? <Loader /> : <div>lang selector here</div> }
</>
)
But when I use setTimeout (even with zero time) on setLanguage
the loader is displayed until the lang changes:
const [isLoading, setIsLoading] = useState(false)
const [language, setLanguage] = useState(userPreferences.lang);
const handleChangeLanguage = (lang) => {
setIsLoading(true);
setTimeout(() => setLanguage(lang), 0); // <= change here
}
useEffect(() => {
i18n.changeLanguage(language).then(() => setIsLoading(false) );
},[language])
return (
<>
{isLoading ? <Loader /> : <div>lang selector here</div> }
</>
)
Why does it behave like that, and can I set it somehow to avoid setTimeout
?
Thanks.
CodePudding user response:
try this code instead of your function and remove useEffect
const handleChangeLanguage = async(lang) => {
setIsLoading(true);
try {
const res = await i18n.changeLanguage(lang);
setIsLoading(false)
} catch (error) {
console.log(error)
setIsLoading(false)
}
}
CodePudding user response:
Try using setImmediate()
instead of setTimeout()