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

NextJS(App Router)后端数据获取后无法渲染至HTML元素

问题:Next.js App Router 数据渲染异常

已确认后端数据成功获取(console.log能输出完整数据),但无法将其渲染到HTML元素中;将数据库相同数据硬编码为数组时可正常渲染,本地定义的PersonParagraphs数组也能正常显示,尝试多种方法仍未解决。

相关代码

import { PersonData, PersonParagraph } from "@/app/lib/schemas";

// 配置页面选项
export const dynamic = "force-dynamic";
export const revalidate = 10;

async function fetchPersonData(id: string): Promise<PersonData> {
  // 根据ID获取人物数据
  const res = await fetch(
    `${process.env.NEXT_PUBLIC_API_BASE_URL}/api/get_person/${id}`,
    {
      cache: "no-store",
    }
  );

  if (!res.ok) {
    throw new Error("获取人物数据失败");
  }
  return res.json();
}

const Person = async ({
  params,
  searchParams,
}: {
  params: { name: string };
  searchParams: { id?: string };
}) => {
  const { name } = params;
  const id = searchParams.id;

  if (!id) {
    throw new Error("缺少人物ID");
  }

  const personData = await fetchPersonData(id);
  console.log("获取到的人物数据: ", personData)

  return (
    <div className="flex flex-col">
      <NavBar />
      <section className="flex flex-col h-screen w-screen p-32">
        <h2 className="font-medium text-2xl">{personData.bio?.title || ""}</h2>
        <h1 className="font-bold text-4xl pt-4">
          {personData.name || ""}{" "}
          <span className="abo-thar">{personData.title || ""}</span>
        </h1>
        <div className="flex w-full justify-between">
          <p className="w-5/12 pt-12 text-justify">
            {personData.bio?.text || ""}
          </p>
          {personData.imageUrl && (
            <img
              src={personData.imageUrl}
              alt={personData.name || ""}
              className="max-w-96 p-6"
            />
          )}
        </div>
      </section>
      {PersonParagraphs.map((paragraph: PersonParagraph, index: number) => (
        <section
          key={index}
          className="grid grid-cols-6 mt-32 h-screen w-screen grid-rows-6 gap-4 p-24"
        >
          <div className="col-span-3 h-full row-span-3">
            <h2 className="text-right text-[#0e0e2c] text-5xl font-medium my-4">
              {paragraph.title}
            </h2>
            <p className="text-justify w-5/6 text-black text-base font-medium leading-[30px]">
              {paragraph.text}
            </p>
            {paragraph.images?.[2] && (
              <img
                src={paragraph.images[1]}
                alt={`${paragraph.title} - 图片3`}
              />
            )}
          </div>
          <div className="col-span-3 row-span-3 justify-center flex col-start-4">
            {paragraph.images?.[0] && (
              <img
                src={paragraph.images[0]}
                className="w-3/6 max-h-80"
                alt={`${paragraph.title} - 图片1`}
              />
            )}
          </div>
          <div className="col-span-3 row-span-3 justify-center flex row-start-4">
            {paragraph.images?.[1] && (
              <img
                src={paragraph.images[1]}
                className="w-3/6"
                alt={`${paragraph.title} - 图片2`}
              />
            )}
          </div>
          <div className="col-span-3 row-span-3 col-start-4 justify-center flex row-start-4">
            {paragraph.images?.[1] && (
              <img
                src={paragraph.images[1]}
                className="w-3/6"
                alt={`${paragraph.title} - 图片2(重复)`}
              />
            )}
          </div>
        </section>
      ))}
    </div>
  );
};

export default Person;

排查与解决方案

  1. 核对数据结构与类型定义
    检查console.log输出的personData实际结构,和PersonData接口定义是否完全匹配:

    • 字段名是否大小写一致(比如后端返回Bio而非bio,或Name而非name)
    • 嵌套结构是否正确(比如bio是否为对象,而非字符串或null)
    • 字段类型是否匹配(比如title是否为字符串,而非数字或其他类型)
  2. 调试可选链与默认值
    在渲染位置临时添加调试输出,确认字段是否存在:

    <h2 className="font-medium text-2xl">
      {console.log('bio:', personData.bio)}
      {personData.bio?.title || "无标题"}
    </h2>
    

    如果personData.bio为null,可以调整为personData?.bio?.title || "",增加顶层可选链。

  3. 验证后端响应格式
    确认后端返回的Content-Type为application/json,避免res.json()解析出错。可以在fetchPersonData中添加日志:

    console.log('响应头Content-Type:', res.headers.get('Content-Type'));
    
  4. 检查样式隐藏问题
    确认渲染元素没有被CSS隐藏(比如文字颜色与背景色一致、元素被display: none或opacity: 0覆盖),可以临时给元素添加border: 1px solid red排查。

  5. 强制类型断言(临时排查)
    如果类型定义和实际数据有差异,可临时用类型断言跳过检查,验证是否能渲染:

    const personData = await fetchPersonData(id) as unknown as {
      name: string;
      title: string;
      bio: { title: string; text: string };
      imageUrl: string;
    };
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:47:33