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

React Router v6+:如何用useLoaderData实现无刷新删除数据

解决react-router-dom@6删除数据后无刷新更新页面问题

问题根源

你当前代码中,products()只是返回useLoaderData()的结果,但useLoaderData()仅在组件挂载或路由首次匹配时加载数据,手动调用该函数无法触发loader重新获取最新数据,因此删除后页面数据不会自动更新。


解决方案1:使用useRevalidator手动触发loader更新

这种方法无需修改路由配置,只需在组件内添加useRevalidator hook,在删除成功后触发数据重新加载。

修改后的Product组件代码:

import { useLoaderData, useRevalidator } from "react-router-dom";
import axiosClient from "../../../axios-client"

export const ProductData = () => {
  return axiosClient.get('admin/product')
    .then(({ data }) => data.data)
    .catch((error) => error)
}

export default function Product() {
  // 直接赋值useLoaderData的结果,无需封装成函数
  const products = useLoaderData();
  const { revalidate } = useRevalidator();

  const ProductDelete = async(id) => {
    try {
      await axiosClient.delete(`admin/product/delete/${id}`);
      // 删除成功后触发loader重新获取数据
      await revalidate();
    } catch (error) {
      console.error("删除失败:", error);
    }
  }

  return (
    <div className="flex flex-col">
      <table className="min-w-full divide-y divide-gray-500">
        <thead className="bg-red-500">
          <tr>
            <th>id</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-gray-200">
          {products && products.map((product) => (
            <tr key={product.id}>
              <td className="px-6 py-4 text-sm font-medium text-gray-800 whitespace-nowrap">
                <button onClick={()=>ProductDelete(product.id)}>Delete</button>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

解决方案2:使用路由action + Form组件(推荐)

这是react-router-dom@6.4+推荐的最佳实践,将删除逻辑放到路由的action中,通过Form组件提交请求,完成后自动触发loader重新加载数据。

步骤1:修改组件,添加action函数并使用Form组件

import { useLoaderData, Form } from "react-router-dom";
import axiosClient from "../../../axios-client"

export const ProductData = () => {
  return axiosClient.get('admin/product')
    .then(({ data }) => data.data)
    .catch((error) => error)
}

// 定义删除的action函数
export const ProductDeleteAction = async ({ request }) => {
  const formData = await request.formData();
  const id = formData.get('id');
  try {
    await axiosClient.delete(`admin/product/delete/${id}`);
    return { success: true };
  } catch (error) {
    return { error: error.message };
  }
}

export default function Product() {
  const products = useLoaderData();

  return (
    <div className="flex flex-col">
      <table className="min-w-full divide-y divide-gray-500">
        <thead className="bg-red-500">
          <tr>
            <th>id</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-gray-200">
          {products && products.map((product) => (
            <tr key={product.id}>
              <td className="px-6 py-4 text-sm font-medium text-gray-800 whitespace-nowrap">
                {/* 使用react-router的Form组件提交删除请求 */}
                <Form method="POST">
                  <input type="hidden" name="id" value={product.id} />
                  <button type="submit">Delete</button>
                </Form>
              </td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

步骤2:更新路由配置,添加action

import Product, { ProductData, ProductDeleteAction } from "./components/admin/product/IndexProduct"

const router = createBrowserRouter([
  {
    path: "product",
    element: <Product />,
    loader: ProductData,
    action: ProductDeleteAction // 绑定action
  }
]);

两种方案说明

  • 方案1适合快速修改,代码改动小;
  • 方案2符合react-router的设计理念,将数据操作逻辑与组件解耦,更利于维护和扩展。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:31:01