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
相关产品推荐
相关产品推荐

