Wakil Ahmed
Wakil Ahmed

Reputation: 1423

Hydration failed because the initial UI does not match what was rendered on the server - after implementing Remix i18n translation

I've implemented translation in my Remix app using the Remix i18n package. So far, everything works fine when I have a parent component that loads translations from a specific namespace.

However, I'm encountering the hydration error when I use a child component that also loads its translations from a specified JSON file. Interestingly, if I don't use translations in the child component, the errors stop occurring.

Here's the parent component:

import { Card } from "@shopify/polaris";
import { Spacer } from "../components/globalComponents"
import HaveQuestionsCard from "../components/HaveQuestionsCard";


// i18n imports and configurations
import { useTranslation } from "react-i18next";
export let handle = { i18n: "testHome" };   // Loading the translation from "testHome" namespace


export default function TestHome() {

  let { t } = useTranslation("testHome");

  return (
    <>
      <Spacer height={"10rem"} />
      <Card>
        <h1>
          {t("title")}
        </h1>
      </Card>

      <Spacer height={"2rem"} />

      <HaveQuestionsCard />
    </>
  )
}

And here's the child component:

import { Card, Text, InlineStack, Link } from "@shopify/polaris";
import { Spacer } from "./globalComponents";
import SupportImg from "../media/bundle/support.svg";

// i18n imports and configurations
import { useTranslation } from "react-i18next";
export let handle = { i18n: "haveQuestionsCard" };     // Loading the specific "haveQuestionsCard" namespace


export default function HaveQuestionsCard() {

   // Loading the function to load the translation.
  let { t } = useTranslation("haveQuestionsCard");

  return (
    <Card>
      <InlineStack gap={"200"}>
        <Text as="h2" variant="headingMd">
          {t("title")}
        </Text>

        <img alt="" width="8%" height="8%"
          style={{
            objectFit: "cover",
            objectPosition: "center",
          }}
          src={SupportImg}
        />
      </InlineStack>

      <Spacer />

      <Text as="p" variant="bodyMd">
        {t("details")}
      </Text>

      {/* <Spacer /> */}

      <Link monochrome url="#">
        <Text as="h2" variant="bodyMd" fontWeight="medium" tone="subdued">
          {t("link")}
        </Text>
      </Link>
    </Card>
  );
}

Here's how the error looks:

enter image description here

This error is getting so frustrating and any help will be really appreciated. Thanks.

Upvotes: 1

Views: 275

Answers (1)

Alexandre Robert
Alexandre Robert

Reputation: 1

Had a similar problem in a remix app, need to dig further but working on the

export const handle = 
i18n: [ ...some namespaces ],

in the root.tsx file (adding namespace I use on pages with problem) made the console error disappeared

EDIT:

It's been a while but I finally managed to get rid of these hydratation errors.

In my i18n.tsx file I had to add this line:

react: { useSuspense: false }

In my root.tsx I had to add:

export const handle = {
    i18n: ["common", "login", "searchBar"],
}

The array includes the names of all the translation files

Then in my routes/components I had to stop using:

const { t } = useTranslation(["login", "common"]); 

for instance, but instead only call one file only:

const { t } = useTranslation("login");

And if I needed to access other translations in the same component I call the file directly with ns prop:

 {t("logout", { ns: "common" })} 

for instance

Without these changes Remix was not able to access the texts server side, so the html was sent with the translation keys instead of the actual text

Upvotes: 0

Related Questions