React i18next useTranslation Hook во вспомогательном методе

Я использую React с react-i18next

Мой файл index.tsx содержит некоторые компоненты, и я могу использовать там функцию перевода.

index.js
import React, { Suspense } from 'react'
import ReactDOM from 'react-dom';
import * as utils from './Utils';
import './i18n';
import { useTranslation, withTranslation, Trans } from 'react-i18next';

...
  const { t, i18n } = useTranslation();
  //I can use the translate function here
  t("title");
  //call a util function
  utils.helperFunction(...);
...

Здесь все отлично работает. Теперь я создал несколько вспомогательных функций в дополнительном файле

Utils.tsx
...
import { useTranslation, withTranslation, Trans } from 'react-i18next';
...
export function helperFunction(props: any){
   //do stuff

   //now I need some translation here - but useTranslation is not working?
   const { t, i18n } = useTranslation();
   t("needTranslation");
}

Как я могу использовать ту же логику перевода внутри моей вспомогательной функции? (без передачи функции t во вспомогательный метод)

Или здесь использование крючка - неправильный подход?

Возникает следующая ошибка

React Hook "useTranslation" is called in function "helperFunction" which is neither a React function component or a custom React Hook function  react-hooks/rules-of-hooks

person Evil_skunk    schedule 18.12.2019    source источник


Ответы (2)


Я исправил свою проблему, больше не используя ловушку useTranslation

Вместо этого я переместил инициализацию i18n в файл (i18n.tsx - экспорт i18n) и импортирую и использую его в моем классе Utils.

Мой файл Utils.tsx не похож на этот Utils.tsx

...
import i18n from '../i18n';
...
export function helperFunction(props: any){
   //do stuff

   //use imported i18n and call the t() method
   i18n.t("needTranslation");
}
i18n.tsx
import i18n from "i18next";
import Backend from 'i18next-xhr-backend';
import { initReactI18next } from 'react-i18next';

i18n
  .use(Backend) 
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    lng: "es",
    fallbackLng: 'en',
    backend: {
      loadPath: '/static/locales/{{lng}}/{{ns}}.json'
    },    
    interpolation: {
      escapeValue: false
    }
  });

  export default i18n;
person Evil_skunk    schedule 19.12.2019
comment
Это правильный ответ. Я хочу упомянуть, что это не работает, когда вы хотите использовать пространства имен. Вам нужно написать i18n.t (пространство имен: needTranslation) - person Danny van Holten; 31.05.2021

Похоже, вы забыли цитату t("needTranslation); -> t("needTranslation");

После запуска вашего кода я понимаю, почему ваш код не работает. Если вы хотите извлечь логику компонента в функции многократного использования, вам следует создать собственный хук. Дополнительную информацию см. В документации.

import React from "react";
import ReactDOM from "react-dom";
import i18n from "i18next";
import "./i18n.js";
import { useTranslation, initReactI18next } from "react-i18next";

i18n
  .use(initReactI18next) 
  .init({
    resources: {
      en: {
        translation: {
          title: "Hello world",
          subtitle: "Hello stackoverflow"
        }
      }
    },
    lng: "en",
    fallbackLng: "en",

    interpolation: {
      escapeValue: false
    }
  });

function App() {
  const { t } = useTranslation();
  useHelperFunction();
  return <h1>{t("title")}</h1>;
}

// you need to turn the helper function into a hook
function useHelperFunction() {
  const { t } = useTranslation();
  return <h2>{t("subtitle")}</h2>;
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
person Jurrian    schedule 18.12.2019
comment
вы правы, я просто применил свой пример для SO и не проверял синтаксис, но моя проблема не связана с синтаксисом, я обновил код и добавил сообщение об ошибке - person Evil_skunk; 18.12.2019
comment
Спасибо за помощь, но мне жаль, что у меня не получилось (та же ошибка в моем приложении), но теперь я использую i18n без крючка, и все работает нормально (см. Мой ответ) - person Evil_skunk; 19.12.2019