如何正确使用React Memo与renderItem优化列表点击及重渲染?
React列表点击事件与Memo优化方案
问题分析
你的代码存在两个核心问题:
renderItem在组件外部定义却调用useNavigateHook,违反了Hook只能在组件/自定义Hook顶层调用的规则- 每次重渲染时,
renderItem函数和onClick内的箭头函数都会生成新引用,可能导致子组件TableDashboardBox触发不必要的重渲染
优化步骤
1. 修正Hook调用并缓存渲染函数
将renderItem移到组件内部,用useCallback缓存函数引用,确保只有依赖项变化时才重新生成。同时优化点击事件的写法,减少不必要的函数创建。
2. 给子组件添加Memo优化
如果TableDashboardBox尚未做优化,用React.memo包裹它,让子组件仅在props浅对比变化时重渲染。
优化后完整代码
import { useNavigate, useCallback } from 'react'; import { mockAvailableCarsData } from '../../utils/mockData'; import TableDashboardBox from '../TableDashboardBox/TableDashboardBox'; import { IAvailableCarsData } from './types'; // 给TableDashboardBox添加Memo优化(若组件本身未实现) const MemoizedTableDashboardBox = React.memo(TableDashboardBox); function AvailableCars() { const navigate = useNavigate(); // 用useCallback缓存renderItem,依赖仅为稳定的navigate const renderItem = useCallback((el: IAvailableCarsData) => { const handleRowClick = () => navigate(`/cars/${el.id}`); return ( <tr onClick={handleRowClick} className="meetings-tr"> <td>{el.car} - {el.mark}</td> <td>{el.fuel}</td> </tr> ); }, [navigate]); return ( <MemoizedTableDashboardBox<IAvailableCarsData> data={mockAvailableCarsData} headerData={['Auto', 'Reichweite']} renderItem={renderItem} keyExtractor={({id}) => id.toString()} title="Available" moreLinkURL="/cars" createButtonText={null} classNameBox="w-100 mt-24 av-cars-box" /> ); } export default AvailableCars;
关键优化说明
- useCallback缓存renderItem:保证函数引用稳定,只有当
navigate变化时才重新生成,避免子组件因props引用变化触发重渲染 - 点击事件处理:同一列表项的
handleRowClick引用保持稳定,仅当列表项本身变化时才生成新函数 - React.memo优化子组件:让
TableDashboardBox仅在props实际内容变化时重渲染,配合稳定的renderItem大幅减少不必要的渲染开销
内容的提问来源于stack exchange,提问作者mastermaster11
相关产品推荐
相关产品推荐

