如何将.map逻辑抽象为独立React组件,实现列表类API调用渲染复用
实现方案
核心思路
封装一个带泛型的通用列表组件,将列表容器、遍历逻辑、点击事件绑定统一收敛到组件内部,对外暴露数据源、自定义渲染项、点击回调三个核心配置入口,既实现了公共逻辑复用,又保留了业务自定义的灵活度。
1. 封装通用列表组件
import React from 'react'; import { List, TouchableOpacity } from '你当前使用的组件库路径'; // 泛型T支持适配任意接口返回的列表数据结构 type GenericListProps<T> = { // 接口返回的列表数据源 dataSource: T[]; // 自定义渲染列表项的方法,可拿到当前项的完整数据 renderItem: (item: T) => React.ReactNode; // 列表项点击回调,可拿到当前点击项的完整数据 onItemPress?: (item: T) => void; // 可根据需求扩展更多公共配置,比如空状态、加载态、分割线等 } export function GenericList<T>({ dataSource, renderItem, onItemPress }: GenericListProps<T>) { return ( <List> {dataSource.map((item, index) => ( <TouchableOpacity key={index} onPress={() => onItemPress?.(item)} > {renderItem(item)} </TouchableOpacity> ))} </List> ); }
如果需要优化列表渲染性能,也可以额外暴露key的取值规则配置,避免用index作为key:
// 扩展Props定义 type GenericListProps<T> = { // ...其他prop不变 getKey: (item: T) => string | number; } // 组件内使用 key={getKey(item)}
2. 业务场景使用示例
原有车库列表场景
import { GenericList } from './GenericList'; // 你的业务页面组件 const GaragePage = () => { const [garage, setGarage] = useState<Car[]>([]); // 接口请求获取garage数据逻辑省略 // 点击车辆时的自定义操作,可拿到当前车辆的完整数据 const handleCarPress = (car: Car) => { doSomething(car.color); } return ( <GenericList<Car> dataSource={garage} onItemPress={handleCarPress} renderItem={(car) => <Car name={car.name} />} // 如果配置了getKey,这里传入getKey={(car) => car.id}即可 /> ); }
其他类型列表场景(比如用户列表)
不需要修改通用组件,直接传入对应类型的数据源和配置即可复用:
const UserPage = () => { const [userList, setUserList] = useState<User[]>([]); const handleUserPress = (user: User) => { navigate(`/user-detail/${user.id}`); } return ( <GenericList<User> dataSource={userList} onItemPress={handleUserPress} renderItem={(user) => <UserCard avatar={user.avatar} nickName={user.nickName} />} /> ); }
方案优势
- 公共逻辑完全复用,不需要在每个列表页面重复写
<List>容器和.map遍历代码 - 泛型适配任意数据结构,不会限制业务接口的字段定义
- 自定义能力灵活,渲染逻辑、点击处理逻辑都由业务层自行控制,可拿到每个列表项的完整数据做任意操作
- 后续如果要统一修改所有列表的样式、新增公共能力(比如下拉刷新、加载更多),只需要修改通用组件一处即可全局生效
内容的提问来源于stack exchange,提问作者user16244117
相关产品推荐
相关产品推荐

