如何在ReactJS中创建通用组件以减少重复组件的编写?
如何创建可复用的React列表选择组件
嘿,很高兴帮你解决这个组件复用的问题!你已经写了两个高度相似的选择列表组件,现在要把它们抽象成一个通用的版本,核心思路就是把变化的部分抽成组件的props参数,比如请求URL、select的name属性这些,而不变的逻辑(比如获取数据、渲染选项)留在组件内部复用。
步骤1:编写可复用的CustomListComponent
我们把重复的逻辑保留,将需要动态调整的参数通过props传入:
import { Component } from 'react'; class CustomListComponent extends Component { constructor(props) { super(props); this.state = { options: [] }; } componentDidMount() { // 从props中获取请求地址,替代原来硬编码的URL fetch(this.props.reqUrl, { method: 'GET' }) .then(response => response.json()) .then(data => { this.setState({ options: data }); }) // 建议加上错误处理,避免请求失败导致页面异常 .catch(error => console.error('获取列表数据失败:', error)); } render() { // 从props中获取select的name和样式类,样式类可以设置默认值 const { selectName, selectClass = 'form-control' } = this.props; const { options } = this.state; return ( <select name={selectName} className={selectClass}> {/* 可以默认添加空选项,提升用户体验 */} <option value="">请选择</option> {options.map(item => ( <option key={item.id} value={item.code}> {item.name} </option> ))} </select> ); } } export default CustomListComponent;
步骤2:使用CustomListComponent替代原有组件
现在你只需要通过传递不同的props,就能生成原来的两个选择列表:
<div class="form-group"> <CustomListComponent reqUrl="/api/get-code-list/" selectName="code_list" /> </div> <div class="form-group"> <CustomListComponent reqUrl="/api/get-location-list/" selectName="location_list" /> </div>
额外优化建议(可选)
为了让组件更通用,适配更多场景,你还可以扩展更多props:
- 如果不同接口返回的字段名不一样(比如有的用
value而非code,label而非name),可以添加valueKey和labelKeyprops,设置默认值 - 添加加载状态提示,避免数据未返回时用户看到空列表
- 支持传入占位符文本
优化后的组件示例:
class CustomListComponent extends Component { constructor(props) { super(props); this.state = { options: [], isLoading: true }; } componentDidMount() { const { reqUrl } = this.props; fetch(reqUrl, { method: 'GET' }) .then(response => response.json()) .then(data => { this.setState({ options: data, isLoading: false }); }) .catch(error => { console.error('获取列表数据失败:', error); this.setState({ isLoading: false }); }); } render() { const { selectName, selectClass = 'form-control', valueKey = 'code', labelKey = 'name', placeholder = '请选择' } = this.props; const { options, isLoading } = this.state; // 加载状态下显示禁用的加载提示 if (isLoading) { return <select className={selectClass} disabled><option>加载中...</option></select>; } return ( <select name={selectName} className={selectClass}> <option value="">{placeholder}</option> {options.map(item => ( <option key={item.id} value={item[valueKey]}> {item[labelKey]} </option> ))} </select> ); } }
这样即使遇到不同格式的接口,你也能灵活使用:
<CustomListComponent reqUrl="/api/get-category-list/" selectName="category_list" valueKey="id" labelKey="categoryName" placeholder="请选择分类" />
内容的提问来源于stack exchange,提问作者Nafi Pantha
相关产品推荐
相关产品推荐

