useState 钩子的行为与预期不同

发布于 2025-01-18 20:49:04 字数 1288 浏览 2 评论 0原文

我的 React 应用程序中使用 i18next 有一个简单的语言选择器(en、cs)。语言的更改(应用所有翻译并重新渲染应用程序)大约需要 2 秒。

与此同时,我想显示一个加载程序,但这似乎没有按预期工作。

我有两种情况。第一个不显示 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> }
    </>
)

但是当我在 setLanguage 上使用 setTimeout(即使时间为零)时,会显示加载程序,直到语言发生变化:

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> }
    </>
)

为什么它的行为是这样的,我可以以某种方式设置它以避免 setTimeout 吗?

谢谢。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ヅ她的身影、若隐若现 2025-01-25 20:49:04

尝试此代码而不是您的函数并删除 useEffect

const handleChangeLanguage = async(lang) => {
    setIsLoading(true);
      try {
     const res = await i18n.changeLanguage(lang);
    setIsLoading(false)
        } catch (error) {
    console.log(error)
    setIsLoading(false)
       }
} 

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

风吹雪碎 2025-01-25 20:49:04

尝试使用 setImmediate() 而不是 setTimeout()

Try using setImmediate() instead of setTimeout()

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文