如何用useMemo与useEffect优化React Table数据加载及行选中编辑
优化重渲染与实现选中行可编辑
一、减少不必要的重渲染
1. 优化useFetch钩子
- 修复异步逻辑:避免混用
await和.then(),改用try/catch统一处理错误 - 添加请求取消机制:使用
AbortController防止组件卸载后仍更新状态,避免内存泄漏 - 移除无效的
console.log(data):状态更新是异步操作,此处打印的始终是旧值
修改后的useFetch:
export const useFetch = url => { const [data, setData] = useState([]); const [error, setError] = useState(null); const [loading, setLoading] = useState(false); useEffect(() => { const controller = new AbortController(); const signal = controller.signal; const fetchData = async () => { setLoading(true); try { const response = await axios.get(url, { signal }); setData(response.data); setError(null); } catch (err) { if (!signal.aborted) { setError(err); } } finally { if (!signal.aborted) { setLoading(false); } } }; fetchData(); return () => controller.abort(); }, [url]); return { data, error, loading }; };
2. 记忆化处理列配置
在Users组件中,使用useMemo缓存列配置,仅当data变化时重新生成,避免每次渲染都创建新的columns数组触发DataTable重渲染:
const columns = useMemo(() => { if (!data || data.length === 0) return []; return Object.keys(data[0]).map(key => ({ Header: key.toLocaleUpperCase(), accessor: key })); }, [data]);
3. 记忆化DataTable组件
用React.memo包裹DataTable,仅当columns或data变化时才重新渲染:
export default React.memo(DataTable);
二、实现选中行可编辑
1. 创建可编辑单元格组件
新建EditableCell.jsx,支持在编辑模式和展示模式间切换:
import React, { useState } from 'react'; const EditableCell = ({ cell: { value }, row, column: { accessor } }) => { const [isEditing, setIsEditing] = useState(false); const [inputValue, setInputValue] = useState(value); const handleSave = () => { // 此处可添加更新数据的API调用逻辑 console.log(`更新${accessor}为${inputValue},行数据:`, row.original); setIsEditing(false); }; return ( <td> {isEditing ? ( <> <input type="text" value={inputValue} onChange={(e) => setInputValue(e.target.value)} /> <button onClick={handleSave}>保存</button> <button onClick={() => setIsEditing(false)}>取消</button> </> ) : ( <span onClick={() => setIsEditing(true)}>{value}</span> )} </td> ); }; export default EditableCell;
2. 修改DataTable组件
- 获取选中行数据:从
useRowSelect返回的selectedFlatRows中提取选中行ID - 记忆化选中行ID集合:避免每次渲染都重新创建集合
- 条件渲染单元格:仅当行被选中时,渲染可编辑单元格
修改后的DataTable关键部分:
import EditableCell from './EditCell'; import React, { useMemo } from 'react'; const DataTable = ({ columns, data }) => { // ...其他代码不变 const { // ...其他属性 selectedFlatRows, } = tableInstance; // 记忆化选中行ID const selectedRowIds = useMemo(() => { return new Set(selectedFlatRows.map(row => row.id)); }, [selectedFlatRows]); // ...其他代码不变 return ( // ...其他代码不变 <tbody {...getTableBodyProps()}> {page.map((row, idx) => { prepareRow(row); const isSelected = selectedRowIds.has(row.id); return ( <tr {...row.getRowProps()}> {row.cells.map((cell, idx) => ( <td {...cell.getCellProps()}> {isSelected ? ( <EditableCell cell={cell} row={row} column={cell.column} /> ) : ( cell.render('Cell') )} </td> ))} </tr> ); })} </tbody> // ...其他代码不变 ); }; export default React.memo(DataTable);
这些更改后,重渲染次数会减少到合理范围(初始渲染→加载中→数据加载完成),且只有选中的行会变为可编辑状态。
内容的提问来源于stack exchange,提问作者Shyam
相关产品推荐
相关产品推荐

