Home > Software design >  useState hook behaves differently than expected
useState hook behaves differently than expected

Time:04-04

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()

  • Related