如何创建可复用的可删除React组件 无需重复编写remove函数
方案评估
你当前的核心实现逻辑是符合React单向数据流设计规范的,由父组件控制子组件的存在状态确实是正确的做法,避免了子组件自行操作父级数据的反模式。唯一可以先优化的小细节是:子组件不需要将传入的removeFunc存入自身state,直接调用props上的方法即可,减少冗余状态:
class ChildComponent extends Component { render() { return ( <div> <button onClick={this.props.removeFunc}>Delete Me</button> </div> ); } } export default ChildComponent;
复用删除逻辑的实现方案
针对需要重复编写removeFunc的问题,有三种常用的复用方案,分别适配不同的开发场景:
方案1:高阶组件(HOC)适配类组件
将列表状态维护、删除逻辑封装到公共高阶组件中,需要该能力的父组件直接被HOC包裹即可,无需重复写逻辑:
// 公共HOC封装 const withRemovableList = (WrappedComponent) => { return class extends Component { constructor(props) { super(props); this.state = { listData: props.initialData || [] }; } removeItem = (index) => { this.setState(prev => ({ listData: prev.listData.filter((_, i) => i !== index) })); } render() { return <WrappedComponent listData={this.state.listData} removeItem={this.removeItem} {...this.props} />; } } } // 业务父组件使用示例 class ParentComponent extends Component { render() { return ( <div> {this.props.listData.map((el,i) => <ChildComponent removeFunc={() => this.props.removeItem(i)}/> )} </div> ); } } // 传入初始数据即可使用 export default withRemovableList(ParentComponent);
方案2:自定义Hook适配函数组件(React 16.8+ 推荐方案)
如果使用函数组件,封装自定义Hook的代码更简洁:
// 公共Hook封装 const useRemovableList = (initialData = []) => { const [listData, setListData] = useState(initialData); const removeItem = (index) => { setListData(prev => prev.filter((_, i) => i !== index)); }; return { listData, removeItem }; } // 业务父组件使用示例 const ParentComponent = ({initialData}) => { const { listData, removeItem } = useRemovableList(initialData); return ( <div> {listData.map((el,i) => <ChildComponent removeFunc={() => removeItem(i)}/> )} </div> ); }
方案3:全量封装通用列表组件
如果你的使用场景相似度极高,可以进一步封装完整的可删除列表组件,直接传入数据源和自定义渲染逻辑即可:
const RemovableList = ({data, renderItem}) => { const [listData, setListData] = useState(data); const removeItem = (index) => { setListData(prev => prev.filter((_, i) => i !== index)); }; return ( <div> {listData.map((item, i) => ( <div key={i}> {renderItem(item)} <button onClick={() => removeItem(i)}>删除</button> </div> ))} </div> ) } // 业务侧调用示例 const ParentComponent = () => { return <RemovableList data={[XXX]} renderItem={(item) => <div>{item.content}</div>} /> }
内容的提问来源于stack exchange,提问作者John Bustos
相关产品推荐
相关产品推荐

