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

react-admin+Next.js创建记录时record.section未定义错误

问题:React Admin 创建记录后 record.section 未定义报错

在 Next.js 14.2.14 + React Admin 5.3.0 项目中,创建units记录时触发错误:TypeError: 无法访问属性"name",record.section未定义,但刷新页面后错误消失。仅当recordRepresentation使用嵌套对象record.section.name时出现此问题,设为"name"则正常。


相关代码片段

App.tsx(React Admin 资源配置)

// src/app/admin/App.tsx

const dataProvider = simpleRestProvider("/api");

const App = () => {
  return (
    <Admin dataProvider={dataProvider}>
      {/* ... */}
      <Resource
        name="units"
        list={UnitList}
        create={UnitCreate}
        edit={UnitEdit}
        recordRepresentation={(record) => `${record.section.name} - ${record.name}`}
      />
      {/* ... */}
    </Admin>
  );
};

接口 POST 实现(route.ts)

// src/app/api/(admin)/units/route.ts

import { auth } from "@/auth";
import { db } from "@/db";
import { units } from "@/db/schema";
import { NextResponse } from "next/server";

export const POST = async (req: Request) => {
  const session = await auth();

  if (!session) {
    return new NextResponse("Unauthorized", { status: 401 });
  }
  if (!session.user || session.user.role !== "admin") {
    return new NextResponse("Forbidden", { status: 403 });
  }

  const body = await req.json();

  const data = await db
    .insert(units)
    .values({
      ...body,
    })
    .returning();

  return NextResponse.json(data[0]);
};

问题原因

创建记录后,React Admin 会立即使用接口返回的新记录渲染recordRepresentation,但当前POST接口返回的data[0]是 Drizzle 插入后直接返回的基础记录——仅包含sectionId,没有嵌套的section对象(关联查询只在GET接口中通过with: { section: true }实现)。刷新页面后调用的GET接口返回了带完整关联数据的记录,因此错误消失。

添加隐藏的section.name字段无效,因为该字段仅在列表页生效,不影响创建接口返回的记录结构。


解决方案

方案1:修改POST接口,返回带关联section的完整记录

插入记录后,通过新记录的id查询包含关联section的完整数据再返回:

export const POST = async (req: Request) => {
  // 省略权限校验代码
  const body = await req.json();

  // 插入基础记录
  const inserted = await db
    .insert(units)
    .values({ ...body })
    .returning();

  // 查询包含section关联的完整记录
  const fullRecord = await db.query.units.findFirst({
    where: (unitsTable, { eq }) => eq(unitsTable.id, inserted[0].id),
    with: { section: true },
  });

  return NextResponse.json(fullRecord);
};

方案2:在recordRepresentation中添加空值保护

避免因section不存在导致报错,同时保证显示友好:

recordRepresentation={(record) => {
  const sectionName = record.section?.name || `未关联章节(ID: ${record.sectionId})`;
  return `${sectionName} - ${record.name}`;
}}

方案3:自定义DataProvider,覆盖create方法

基于simpleRestProvider扩展create方法,创建后自动调用getOne获取完整记录:

import { simpleRestProvider, DataProvider } from 'react-admin';

const dataProvider: DataProvider = {
  ...simpleRestProvider("/api"),
  create: async (resource, params) => {
    // 执行原创建请求
    const createResponse = await simpleRestProvider("/api").create(resource, params);
    // 获取完整记录
    const fullRecord = await simpleRestProvider("/api").getOne(resource, { id: createResponse.data.id });
    return { ...createResponse, data: fullRecord.data };
  },
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 01:53:19