You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何结合React Suspense与Trans组件实现翻译内容异步加载?

如何在Trans组件中实现翻译文本内异步加载内容

我希望实现翻译句子中部分内容的异步加载,尝试使用Trans组件但运行时出现错误:

Unhandled Runtime Error
Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.

我的尝试代码如下:

"use client";

import { Suspense } from "react";
import { Trans } from "react-i18next";

const mockedFetch = (delay: number) => {
  return new Promise<string>((resolve) => {
    setTimeout(() => {
      const last4DigitsOfCard = "3423";
      resolve(last4DigitsOfCard);
    }, delay);
  });
};

function PersonalizedNumber() {
  const delay = 2_000;
  const sentencePromise = mockedFetch(delay);
  return sentencePromise; // 这里直接返回Promise,导致报错
}

function Loading() {
  return <div>Loading...</div>;
}

function Last4DigitsOfCard() {
  return (
    <Suspense fallback={<Loading />}>
      <PersonalizedNumber />
    </Suspense>
  );
}

export function YourPrepaidCardEndingInLastFour({
  locale,
}: {
  locale: string;
}) {
  return (
    <Trans
      locale={locale}
      i18nKey="yourPrepaidCardIsReady"
      components={{
        last4DigitsOfCard: <Last4DigitsOfCard />,
      }}
    />
  );
}

翻译键值:

"yourPrepaidCardIsReady": "Your prepaid card ending in <last4DigitsOfCard/> is active and ready to use."

问题原因

PersonalizedNumber组件直接返回了Promise,而React组件的返回值必须是React元素、null或字符串,不能是Promise。Suspense需要配合能抛出Promise的异步数据逻辑,而非组件直接返回Promise。

解决方法

使用React 18+的use钩子(仅支持客户端组件),它可以直接处理Promise,在Promise pending时自动抛出Promise触发Suspense的fallback,resolved后返回数据。修改后的代码如下:

"use client";

import { Suspense, use } from "react";
import { Trans } from "react-i18next";

const mockedFetch = (delay: number) => {
  return new Promise<string>((resolve) => {
    setTimeout(() => {
      const last4DigitsOfCard = "3423";
      resolve(last4DigitsOfCard);
    }, delay);
  });
};

function PersonalizedNumber() {
  const delay = 2_000;
  // 使用use钩子处理异步Promise,pending时自动触发Suspense
  const last4Digits = use(mockedFetch(delay));
  // 返回React元素而非Promise
  return <span>{last4Digits}</span>;
}

function Loading() {
  return <div>Loading...</div>;
}

function Last4DigitsOfCard() {
  return (
    <Suspense fallback={<Loading />}>
      <PersonalizedNumber />
    </Suspense>
  );
}

export function YourPrepaidCardEndingInLastFour({
  locale,
}: {
  locale: string;
}) {
  return (
    <Trans
      locale={locale}
      i18nKey="yourPrepaidCardIsReady"
      components={{
        last4DigitsOfCard: <Last4DigitsOfCard />,
      }}
    />
  );
}

关键修改点

  1. 引入React的use钩子,用它处理异步请求的Promise
  2. PersonalizedNumber组件不再返回Promise,而是返回包裹异步数据的<span>元素
  3. use钩子会自动处理Promise的pending状态:当Promise未完成时,抛出Promise让上层Suspense捕获并显示loading;当Promise resolved后,返回数据并渲染

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 12:33:31