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

使用useLoaderData与shadcn-ui DataTable时的TypeScript类型错误

解决useLoaderData与shadcn-ui DataTable的类型不匹配问题

问题根源

useLoaderData 默认返回类型为 unknown,而shadcn-ui的DataTable要求data属性必须是定义好的PatientColumn[]类型;同时在Heading组件中访问data?.length时,unknown类型也会触发类型检查错误。

解决方案

1. 为Loader函数指定返回类型

给patientDataLoader明确标注返回类型为Promise<PatientColumn[]>,同时让axios请求指定响应数据类型,确保TypeScript能识别返回数据的结构:

export const patientDataLoader = async (): Promise<PatientColumn[]> => {
  // 给axios.get指定泛型,明确响应数据类型
  const response = await axios.get<PatientColumn[]>("http://localhost:3000/api/patients");
  return response.data;
}

2. 为useLoaderData返回值做类型断言

由于部分版本的react-router-dom中useLoaderData不支持直接传入泛型参数,我们可以通过类型断言将返回值转为PatientColumn[]:

const DashboardPage: React.FC = () => {
  const navigate = useNavigate();
  // 类型断言明确data的类型
  const data = useLoaderData() as PatientColumn[];

  return (
    // ... 原有JSX代码
  );
};

3. 验证类型匹配

修改后,data的类型变为PatientColumn[],既满足DataTable对data属性的类型要求,也能正常访问data.length而不触发类型错误。

修改后的完整代码片段

import { ColumnDef } from "@tanstack/react-table";
import { Plus } from "lucide-react";
import { Button } from "@/components/ui/button";
import Heading from "@/components/ui/heading";
import { Separator } from "@/components/ui/separator";
import { DataTable } from "@/components/ui/data-table";
import { useLoaderData, useNavigate } from "react-router-dom";
import axios from "axios";

type PatientColumn = {
  id: string;
  fullName: string;
  age: string;
  sex: string;
  phone: string;
  email: string;
  doctor: string;
  injury: string;
  dateOfVisit: string;
};

// 明确Loader返回类型
export const patientDataLoader = async (): Promise<PatientColumn[]> => {
  const response = await axios.get<PatientColumn[]>("http://localhost:3000/api/patients");
  return response.data;
}

const DashboardPage: React.FC = () => {
  const navigate = useNavigate();
  // 类型断言转换数据类型
  const data = useLoaderData() as PatientColumn[];

  return (
    <div className="flex-col">
      <div className="flex-1 space-y-4 p-8 pt-1">
        <div className="flex items-center justify-between">
          <Heading
            title={`Patients List (${data.length || 0})`}
            description="Manage patients information "
          />
          <Button onClick={() => navigate(`/dashboard/patient`)}>
            <Plus className="mr-2 w-4 h-4" />
            Add New
          </Button>
        </div>
        <Separator />
        <DataTable columns={columns} data={data} searchKey="fullName"/>
      </div>
    </div>
  );
};

export default DashboardPage;

const columns: ColumnDef<PatientColumn>[] = [
  {
    accessorKey: "fullName",
    header: "Full name",
  },
  {
    accessorKey: "age",
    header: "Age",
  },
  {
    accessorKey: "sex",
    header: "Sex",
  },
  {
    accessorKey: "phone",
    header: "Phone",
  },
  {
    accessorKey: "email",
    header: "Email",
  },
  {
    accessorKey: "doctor",
    header: "Doctor",
  },
  {
    accessorKey: "injury",
    header: "Injury",
  },
  {
    accessorKey: "dateOfVisit",
    header: "Date",
  },
];

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 10:05:00