如何将仅图片路径不同的两个React组件文件合并为一个?
React高重复组件合并复用方案
两个组件的UI结构、点击交互逻辑完全一致,唯一差异是列表项封面图的取值路径,只需将这个差异点抽为可配置的入参,即可用单个通用组件覆盖两个场景,彻底消除代码冗余。
核心思路
把会变的部分(图片取值规则)通过props传入组件,固定不变的结构和逻辑全部留在公共组件内部维护,后续如果要改样式、改交互逻辑,只需要改一次公共组件即可,不用同步修改多份代码。
方案1:高扩展性实现(推荐)
将图片地址的获取逻辑封装为函数作为props传入,后续新增同类列表(比如专辑、歌手列表)只要传入对应取值规则,不需要修改公共组件代码。
公共组件代码
const MediaList = props => { const handleClick = e => { props.onClick(e.target.title); } return ( <section id={props.selectedValue} className="column column__hidden" onClick={handleClick}> <a className="link__decoration link__track hover__track link__one" href="#"> <div> {props.items.map((item, idx) => <div className="container" key={idx + 1} title={item.id} > <div className="content__track" title={item.id}> <img className="img__tarck" title={item.id} src={props.getImageSrc(item)} /> <div className="name" title={item.id}>{item.name}</div> </div> </div>)} </div> </a> </section> ); }
场景调用示例
- 播放列表场景:
<MediaList selectedValue={/* 对应选中状态值 */} items={playlistItems} onClick={/* 对应点击回调函数 */} getImageSrc={item => item.images?.[0]?.url || ''} />
- 流派分类场景:
<MediaList selectedValue={/* 对应选中状态值 */} items={genreItems} onClick={/* 对应点击回调函数 */} getImageSrc={item => item.icons?.[0]?.url || ''} />
方案2:轻量简化实现
如果后续不会新增其他同类列表场景,也可以直接加一个类型字段做内部判断,不用传函数,写法更简短:
const MediaList = props => { const handleClick = e => { props.onClick(e.target.title); } const getCoverSrc = item => { return props.listType === 'playlist' ? item.images?.[0]?.url || '' : item.icons?.[0]?.url || '' } return ( <section id={props.selectedValue} className="column column__hidden" onClick={handleClick}> <a className="link__decoration link__track hover__track link__one" href="#"> <div> {props.items.map((item, idx) => <div className="container" key={idx + 1} title={item.id} > <div className="content__track" title={item.id}> <img className="img__tarck" title={item.id} src={getCoverSrc(item)} /> <div className="name" title={item.id}>{item.name}</div> </div> </div>)} </div> </a> </section> ); }
调用时传入类型即可:
- 播放列表:
<MediaList listType="playlist" {...其余props} /> - 流派分类:
<MediaList listType="genre" {...其余props} />
代码中新增了可选链
?.和空值兜底,避免接口返回图片数组为空、字段缺失时触发JS报错,比原有直接读取[0].url的写法健壮性更高。
内容的提问来源于stack exchange,提问作者Сергей
相关产品推荐
相关产品推荐

