React i18next 引入了使用 i18n 改变 Hook 顺序的方法

发布于 2025-01-10 22:15:32 字数 4207 浏览 0 评论 0原文

我有一个可重复使用的组件,多次使用来显示不同的下拉按钮。 它使用 i18n。

这是我的代码:

import React from 'react';
import { Dropdown } from 'react-bootstrap';
import shortid from 'shortid';
import { useTranslation } from 'react-i18next';

const PropertyButton = (state, name, handle, list, i18nName) => {

    if (name === "Produttore") {
        console.log("aa")
     }

     const [ t, i18n ] = useTranslation();
    
        return (
               <Dropdown>
                    <Dropdown.Toggle className="choiceButton servingButton btn" key="{shortid.generate()}" 
                        item={name} onSelect={handle}>
                        {t(`wine.attribute.${name}`)}
                    </Dropdown.Toggle>

                    <Dropdown.Menu className="choiceButton servingButton btn">

                        { list === null || list === undefined ? <></> :
                        list.map(item => {
                            const val = item.name === undefined ? item : item.name;
                            return (
                                <Dropdown.Item key={shortid.generate()} kname={name} kvalue={val} onClick={handle}>
                                   { i18nName === "regionList" || i18nName === "produttore" || i18nName === "venditore" ? val : t(`wine.${i18nName}.${val}`)}
                                </Dropdown.Item>
                            )
                        }
                        )}
                    </Dropdown.Menu>
                </Dropdown>
        )
    };

export default PropertyButton;

该组件被调用多次,没有错误。 我认为问题不在于组件的主体,因为它只显示一个按钮。 i18n 或我使用它的方式应该有一些奇怪的东西。

有一种情况,当 name === "Produttore" (我添加了一个 console.log 只是为了放置一个断点),然后踩在 const [ t, i18n ] = useTranslation(); 行生成挂钩错误。

顺便说一句,我使用了 const [ t, i18n ] = useTranslation(); 和 const { t } = useTranslation(); 选项,结果相同。

Warning: React has detected a change in the order of Hooks called by NickSelection. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks

************** 显示如何使用 **********************

根据要求,以下是该组件的使用方式/打电话。 每次调用 PropertyButton 都会返回一个 Dropdown 按钮,并使用传递的参数进行初始化。

所有这些都在运行(以不同的语言),但只有带有 Produttore 的那个(用 ===>>> 箭头表示)会生成错误。

const NickSelection = ({
    regionList,
    mainListContainsEffervescenza, mainListContainsTannicità,
    prezzo, setPrezzo,
    effervescenza, setEffervescenza,
    acidità, setAcidità,
    alcolicità, setAlcolicità,
    tannicità, setTannicità,
    tipologia, setTipologia,
    territorio, setTerritorio,
    produttore, setProduttore, producerList,
    venditore, setVenditore, sellerList
}) => {

    return (

            {/* <Footer */}
            <div className="footer_container footer_container_chat" style={{ zIndex: "6000" }}>
      {PropertyButton(tipologia, "Tipologia", handlePropertyButton, allowedProductTypes, "productType")}
      {PropertyButton(territorio, "Territorio", handlePropertyButton, regionList, "regionList")}
      {PropertyButton(acidità, "Acidità", handlePropertyButton, wineSensations, "sensation")}


      {mainListContainsEffervescenza ? PropertyButton(effervescenza, "Effervescenza", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
      {PropertyButton(alcolicità, "Alcolicità", handlePropertyButton, wineSensations, "sensation")}
      {mainListContainsTannicità ? PropertyButton(tannicità, "Tannicità", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
      {PropertyButton(prezzo, "Prezzo", handlePropertyButton, prices, "prices")}

      { producerList.length > 1 ? 
===>>>  PropertyButton(produttore, "Produttore", handlePropertyButton, producerList, "produttore") : <></> }

      { sellerList.length > 1 ? PropertyButton(venditore, "Venditore", handlePropertyButton, sellerList, "venditore") : <></>}

   </div>

};

export default NickSelection;

I have a reusable component used many times to display different dropdown buttons.
It uses i18n.

Here is my code:

import React from 'react';
import { Dropdown } from 'react-bootstrap';
import shortid from 'shortid';
import { useTranslation } from 'react-i18next';

const PropertyButton = (state, name, handle, list, i18nName) => {

    if (name === "Produttore") {
        console.log("aa")
     }

     const [ t, i18n ] = useTranslation();
    
        return (
               <Dropdown>
                    <Dropdown.Toggle className="choiceButton servingButton btn" key="{shortid.generate()}" 
                        item={name} onSelect={handle}>
                        {t(`wine.attribute.${name}`)}
                    </Dropdown.Toggle>

                    <Dropdown.Menu className="choiceButton servingButton btn">

                        { list === null || list === undefined ? <></> :
                        list.map(item => {
                            const val = item.name === undefined ? item : item.name;
                            return (
                                <Dropdown.Item key={shortid.generate()} kname={name} kvalue={val} onClick={handle}>
                                   { i18nName === "regionList" || i18nName === "produttore" || i18nName === "venditore" ? val : t(`wine.${i18nName}.${val}`)}
                                </Dropdown.Item>
                            )
                        }
                        )}
                    </Dropdown.Menu>
                </Dropdown>
        )
    };

export default PropertyButton;

The component is called several times, with no error.
I don't think the problem is in the body of the component, because it only shows a button. There should be something weird in i18n or in the way I used it.

There is a case, when name === "Produttore" (and I added a console.log just to put a breakpoint), then stepping on the const [ t, i18n ] = useTranslation(); line generates an hook error.

BTW, I used both const [ t, i18n ] = useTranslation(); and const { t } = useTranslation(); options with the identical outcome.

Warning: React has detected a change in the order of Hooks called by NickSelection. This will lead to bugs and errors if not fixed. For more information, read the Rules of Hooks: https://reactjs.org/link/rules-of-hooks

************* SHOWING HOW IT IS USED **********************

As requested, here is how the Component is used/called.
Each call to a PropertyButton returns a Dropdown button, initialized with the passed parameters.

All of them are running (in different languages) but only the one with Produttore (signaled with the ===>>> arrow) generate the error.

const NickSelection = ({
    regionList,
    mainListContainsEffervescenza, mainListContainsTannicità,
    prezzo, setPrezzo,
    effervescenza, setEffervescenza,
    acidità, setAcidità,
    alcolicità, setAlcolicità,
    tannicità, setTannicità,
    tipologia, setTipologia,
    territorio, setTerritorio,
    produttore, setProduttore, producerList,
    venditore, setVenditore, sellerList
}) => {

    return (

            {/* <Footer */}
            <div className="footer_container footer_container_chat" style={{ zIndex: "6000" }}>
      {PropertyButton(tipologia, "Tipologia", handlePropertyButton, allowedProductTypes, "productType")}
      {PropertyButton(territorio, "Territorio", handlePropertyButton, regionList, "regionList")}
      {PropertyButton(acidità, "Acidità", handlePropertyButton, wineSensations, "sensation")}


      {mainListContainsEffervescenza ? PropertyButton(effervescenza, "Effervescenza", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
      {PropertyButton(alcolicità, "Alcolicità", handlePropertyButton, wineSensations, "sensation")}
      {mainListContainsTannicità ? PropertyButton(tannicità, "Tannicità", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
      {PropertyButton(prezzo, "Prezzo", handlePropertyButton, prices, "prices")}

      { producerList.length > 1 ? 
===>>>  PropertyButton(produttore, "Produttore", handlePropertyButton, producerList, "produttore") : <></> }

      { sellerList.length > 1 ? PropertyButton(venditore, "Venditore", handlePropertyButton, sellerList, "venditore") : <></>}

   </div>

};

export default NickSelection;

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

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

发布评论

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

评论(1

黯淡〆 2025-01-17 22:15:32

问题

您已经声明了一个常规 Javascript 函数 PropertyButton 并直接在代码中调用它。最终,您有条件地调用此函数,因此,调用的钩子的顺序发生了变化。

<div className="...." style={{ ... }}>
  {PropertyButton(tipologia, "Tipologia", handlePropertyButton, allowedProductTypes, "productType")}
  {PropertyButton(territorio, "Territorio", handlePropertyButton, regionList, "regionList")}
  {PropertyButton(acidità, "Acidità", handlePropertyButton, wineSensations, "sensation")}

  {mainListContainsEffervescenza ? PropertyButton(effervescenza, "Effervescenza", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
  {PropertyButton(alcolicità, "Alcolicità", handlePropertyButton, wineSensations, "sensation")}
  {mainListContainsTannicità ? PropertyButton(tannicità, "Tannicità", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
  {PropertyButton(prezzo, "Prezzo", handlePropertyButton, prices, "prices")}

  {producerList.length > 1 ? PropertyButton(produttore, "Produttore", handlePropertyButton, producerList, "produttore") : <></> }

  {sellerList.length > 1 ? PropertyButton(venditore, "Venditore", handlePropertyButton, sellerList, "venditore") : <></>}

这违反了 Hooks 规则。

解决方案

尝试将 PropertyButton 转换为 React 组件,呈现为 JSX

import React from 'react';
import { Dropdown } from 'react-bootstrap';
import shortid from 'shortid';
import { useTranslation } from 'react-i18next';

const PropertyButton = ({ state, name, handle, list, i18nName }) => {
  ...
};

export default PropertyButton;

...

<div className="...." style={{ ... }}>
  <PropertyButton
    state={tipologia}
    name="Tipologia"
    handle={handlePropertyButton}
    list={allowedProductTypes}
    i18nName="productType"
  />
  ...etc...

  {mainListContainsEffervescenza && (
    <PropertyButton
      state={effervescenza}
      name="Effervescenza"
      handle={handlePropertyButton}
      list={wineSensationsWith0}
      i18nName="sensation"
    />
  )}
  ...etc...

  {producerList.length > 1 && (
    <PropertyButton
      state={produttore}
      name="Produttore"
      handle={handlePropertyButton}
      list={producerList}
      i18nName="produttore"
    />
  )}

  ...etc...

</div>

Issue

You've declared a regular Javascript function, PropertyButton and invoke it directly in your code. Eventually you are conditionally calling this function, and thus, the order of hooks called has changed.

<div className="...." style={{ ... }}>
  {PropertyButton(tipologia, "Tipologia", handlePropertyButton, allowedProductTypes, "productType")}
  {PropertyButton(territorio, "Territorio", handlePropertyButton, regionList, "regionList")}
  {PropertyButton(acidità, "Acidità", handlePropertyButton, wineSensations, "sensation")}

  {mainListContainsEffervescenza ? PropertyButton(effervescenza, "Effervescenza", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
  {PropertyButton(alcolicità, "Alcolicità", handlePropertyButton, wineSensations, "sensation")}
  {mainListContainsTannicità ? PropertyButton(tannicità, "Tannicità", handlePropertyButton, wineSensationsWith0, "sensation") : <></>}
  {PropertyButton(prezzo, "Prezzo", handlePropertyButton, prices, "prices")}

  {producerList.length > 1 ? PropertyButton(produttore, "Produttore", handlePropertyButton, producerList, "produttore") : <></> }

  {sellerList.length > 1 ? PropertyButton(venditore, "Venditore", handlePropertyButton, sellerList, "venditore") : <></>}

This is a violation of the Rules of Hooks.

Solution

Try converting PropertyButton into a React component, rendered as JSX.

import React from 'react';
import { Dropdown } from 'react-bootstrap';
import shortid from 'shortid';
import { useTranslation } from 'react-i18next';

const PropertyButton = ({ state, name, handle, list, i18nName }) => {
  ...
};

export default PropertyButton;

...

<div className="...." style={{ ... }}>
  <PropertyButton
    state={tipologia}
    name="Tipologia"
    handle={handlePropertyButton}
    list={allowedProductTypes}
    i18nName="productType"
  />
  ...etc...

  {mainListContainsEffervescenza && (
    <PropertyButton
      state={effervescenza}
      name="Effervescenza"
      handle={handlePropertyButton}
      list={wineSensationsWith0}
      i18nName="sensation"
    />
  )}
  ...etc...

  {producerList.length > 1 && (
    <PropertyButton
      state={produttore}
      name="Produttore"
      handle={handlePropertyButton}
      list={producerList}
      i18nName="produttore"
    />
  )}

  ...etc...

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