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

TanStack Table切换状态后,如何从主组件重新获取数据?

无刷新更新TanStack React Table数据的实现方案

核心方案:通过回调触发父组件数据刷新

父组件Customers负责数据获取,只需将「刷新数据的函数」传递到列定义中的Switch组件,在状态更新成功后调用该函数重新拉取数据即可。

步骤1:在Customers组件封装数据刷新函数

将数据获取逻辑封装为可复用函数,并通过props传递给DataTable组件:

// Customers.jsx
import { useState, useEffect } from 'react';
import DataTable from './DataTable';
import columns from './columns';

export default function Customers() {
  const [data, setData] = useState([]);

  // 封装数据获取逻辑
  const fetchDishes = async () => {
    const res = await fetch('/api/dishes');
    const fetchedData = await res.json();
    setData(fetchedData);
  };

  // 初始加载数据
  useEffect(() => {
    fetchDishes();
  }, []);

  return (
    <DataTable 
      data={data} 
      columns={columns} 
      onRefresh={fetchDishes} // 传递刷新函数
    />
  );
}

步骤2:在DataTable组件中转递回调到列渲染

在通用DataTable组件中,将onRefresh回调传递给对应列的cell渲染函数:

// DataTable.jsx
import { useTable } from '@tanstack/react-table';

export default function DataTable({ data, columns, onRefresh }) {
  const table = useTable({
    data,
    columns: columns.map(col => {
      // 针对Available列注入回调
      if (col.accessor === 'available') {
        return {
          ...col,
          cell: props => col.cell({ ...props, onRefresh }),
        };
      }
      return col;
    }),
  });

  // 表格渲染逻辑(省略)
  // ...
}

步骤3:在columns.js中调用刷新回调

修改Available列的Switch组件逻辑,更新数据库后触发刷新:

// columns.js
import { Switch } from 'your-ui-library'; // 替换为你使用的UI库

export default [
  // 其他列定义...
  {
    accessor: 'available',
    header: 'Available',
    cell: ({ row, onRefresh }) => {
      const handleStatusToggle = async () => {
        const dishId = row.original.id;
        const newStatus = !row.original.available;
        
        // 调用后端更新API
        await fetch(`/api/dishes/${dishId}/status`, {
          method: 'PATCH',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ available: newStatus }),
        });

        // 更新成功后触发父组件重新获取数据
        onRefresh();
      };

      return (
        <Switch
          checked={row.original.available}
          onChange={handleStatusToggle}
        />
      );
    },
  },
];

优化方案:乐观更新提升用户体验

为了避免等待API响应的延迟感,可以先本地更新表格状态,再同步后端数据,失败时回滚:

// 修改columns.js中的handleStatusToggle
const handleStatusToggle = async () => {
  const dishId = row.original.id;
  const newStatus = !row.original.available;
  
  // 先本地更新表格状态(乐观更新)
  row.setValue('available', newStatus);

  try {
    // 调用后端API
    await fetch(`/api/dishes/${dishId}/status`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ available: newStatus }),
    });
  } catch (err) {
    // API失败时回滚本地状态
    row.setValue('available', !newStatus);
    alert('状态更新失败,请重试');
  }

  // 最后刷新数据确保与后端一致
  onRefresh();
};

替代方案:全局状态管理(Context/Redux)

如果项目使用全局状态管理,可以将菜品数据存入全局状态,更新状态后自动同步表格:

// 示例:使用React Context
// DishContext.js
import { createContext, useContext, useState, useEffect } from 'react';

const DishContext = createContext();

export function DishProvider({ children }) {
  const [dishes, setDishes] = useState([]);

  const fetchDishes = async () => {
    const res = await fetch('/api/dishes');
    setDishes(await res.json());
  };

  const updateDishStatus = async (dishId, newStatus) => {
    await fetch(`/api/dishes/${dishId}/status`, {
      method: 'PATCH',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ available: newStatus }),
    });
    fetchDishes(); // 更新后重新拉取数据
  };

  useEffect(() => {
    fetchDishes();
  }, []);

  return (
    <DishContext.Provider value={{ dishes, updateDishStatus }}>
      {children}
    </DishContext.Provider>
  );
}

export const useDishes = () => useContext(DishContext);

然后在columns.js中使用全局状态:

// columns.js
import { Switch } from 'your-ui-library';
import { useDishes } from './DishContext';

export default [
  // 其他列...
  {
    accessor: 'available',
    header: 'Available',
    cell: ({ row }) => {
      const { updateDishStatus } = useDishes();
      return (
        <Switch
          checked={row.original.available}
          onChange={() => updateDishStatus(row.original.id, !row.original.available)}
        />
      );
    },
  },
];

Customers组件则直接使用全局状态:

// Customers.jsx
import DataTable from './DataTable';
import columns from './columns';
import { useDishes } from './DishContext';

export default function Customers() {
  const { dishes } = useDishes();
  return <DataTable data={dishes} columns={columns} />;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 16:23:26