React-i18next: App broken with Add a <Suspense fallback=...>

Created on 29 Oct 2020  路  13Comments  路  Source: i18next/react-i18next

馃悰 Bug Report

App wont render and there are errors in console because of "Suspense fallback error" as displayed on the image below:
1

To Reproduce

use https://www.npmjs.com/package/cra-template-redux-typescript
npx create-react-app my-app --template redux-typescript
following https://react.i18next.com/latest/using-with-hooks

App.tsx

import React, { Suspense } from 'react';
import logo from './logo.svg';
import { Counter } from './features/counter/Counter';
import './App.css';
import { useTranslation } from 'react-i18next';

function App(): JSX.Element {
  const { t, i18n } = useTranslation();

  return (
    <Suspense fallback="loading">
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <Counter />
          <p>
            {t('edit')} <code>src/App.tsx</code> {t('and save to reload')}.
          </p>
          <span>
            <span>Learn </span>
            <a
              className="App-link"
              href="https://reactjs.org/"
              target="_blank"
              rel="noopener noreferrer"
            >
              React
            </a>
            <span>, </span>
            <a
              className="App-link"
              href="https://redux.js.org/"
              target="_blank"
              rel="noopener noreferrer"
            >
              Redux
            </a>
            <span>, </span>
            <a
              className="App-link"
              href="https://redux-toolkit.js.org/"
              target="_blank"
              rel="noopener noreferrer"
            >
              Redux Toolkit
            </a>
            ,<span> and </span>
            <a
              className="App-link"
              href="https://react-redux.js.org/"
              target="_blank"
              rel="noopener noreferrer"
            >
              React Redux
            </a>
          </span>
        </header>
      </div>
    </Suspense>
  );
}

export default App;

My only one translation file is in:
public\locales\en-US\translation.json

My i18n.js file. And why it won't work if renamed this to i18n.ts?

import i18n from 'i18next';
import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import { initReactI18next } from 'react-i18next';

i18n
  // load translation using http -> see /public/locales
  // learn more: https://github.com/i18next/i18next-http-backend
  .use(Backend)
  // detect user language
  // learn more: https://github.com/i18next/i18next-browser-languageDetector
  .use(LanguageDetector)
  // pass the i18n instance to react-i18next.
  .use(initReactI18next)
  // init i18next
  // for all options read: https://www.i18next.com/overview/configuration-options
  .init({
    fallbackLng: 'en',
    debug: true,
    react: {
      // useSuspense: false,
    },
    interpolation: {
      escapeValue: false, // not needed for react as it escapes by default
    },
  });

export default i18n;

Expected behavior

App would render correctly.

I can jump over this by inserting

react: {
      // useSuspense: false,
    },

But I wish to use proper way as it is displayed in your tutorial.

Your Environment

  • "i18next": "^19.8.3",
  • "i18next-browser-languagedetector": "^6.0.1",
  • "i18next-http-backend": "^1.0.21",
  • "react": "^17.0.1",
  • "react-dom": "^17.0.1",
  • "react-i18next": "^11.7.3",
  • node -v v12.19.0
  • npm -v 6.14.8

Most helpful comment

If you like this module don鈥檛 forget to star this repo. Make a tweet, share the word or have a look at our https://locize.com to support the devs of this project.

There are many ways to help this project 馃檹

All 13 comments

You are calling "useTranslation" outside of the Suspense component

I don't understand that.
It is nested inside as:

<Suspense fallback="loading">
   ...
   <p>
        {t(...

I used and in index.tsx but it worked. Like here:
This is outside the component which is being translated ( will have the t - hook).

ReactDOM.render(
  <React.StrictMode>
    <Provider store={store}>
      <Suspense fallback="loading...">
        <App />
      </Suspense>
    </Provider>
  </React.StrictMode>,
  document.getElementById('root'),
);

Is it a rule from the documentation or it is expected to wrap the whole app in the Suspense?

The message is: Add a <Suspense fallback=...> component higher in the tree, but you used useTranslation outside of the Suspense component.

More information here: https://github.com/i18next/react-i18next/issues/1026#issuecomment-568770418

These are react rules => https://en.reactjs.org/docs/concurrent-mode-suspense.html

it's rather simple but easy to misunderstand:

function App(): JSX.Element {
  const { t, i18n } = useTranslation();

  return (
    <Suspense fallback="loading">
      <div className="App">
    ...

The Suspense here wraps the div (react element) but not your App which uses useTranslation

@adrai thanks for the https://github.com/i18next/react-i18next/issues/1026#issuecomment-568770418 comment!!! That explains it.

@jamuhl you're the one who described it well so thank to you too! :)
And hey, I've played around, and this won't work too:

<p>
  <Suspense fallback="loading...">
    t('edit')} <code>src/App.tsx</code> {t('and save to reload')}.
  <Suspense>
</p>

or

<Suspense fallback="loading...">
  <p>
    {t('edit')} <code>src/App.tsx</code> {t('and save to reload')}.
  </p>
</Suspense>

So the only solution is to put the <App /> component inside of the <Suspense><App /></Suspense> As a child, and it's a must?
Are there some potential wrongdoings or pitfalls? Will it work for all of the nested components which require translation, or each one of them must be inside the <Suspense> ?

The problem is not the t call but the useTranslation call

Summary of the React documentation link: Suspense is for the early adoption.

So to sum it up for this case and close it: are hooks recommended use for this library?
If yes, is Suspense recommended?

Or to just use HOC or i18n-react Translation component?

Personally, I use always hooks and Suspense... the react community is using this mostly nowadays...

Thanks for that insight!

Last one, referring to my previous comment,

do you use like one major Suspense above the whole app, or you wrap each component individually?

It depends... but usually per page 1 Suspense or for bigger data loading sections

Aha, ok.
Well, I suppose this sums it up.

I'm closing this due to my inexperience and misuse.

Thank you @adrai and @jamuhl very much.

If you like this module don鈥檛 forget to star this repo. Make a tweet, share the word or have a look at our https://locize.com to support the devs of this project.

There are many ways to help this project 馃檹

I will absolutely!!!
I've seen https://locize.com too and it appears as an awesome service - tool.

I'm new at this, but this library seems powerful from the beginning.
Thanks again!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ok2ju picture ok2ju  路  3Comments

Flo-Slv picture Flo-Slv  路  4Comments

jadbox picture jadbox  路  3Comments

a-barbieri picture a-barbieri  路  4Comments

tankpower1 picture tankpower1  路  3Comments