React循环列表场景下如何仅禁用当前被点击的对应按钮
解决方案
问题根因
你当前所有按钮共用了同一个全局布尔类型的isLoading状态,所以只要状态变为true,所有绑定了该状态的按钮都会被禁用。你代码中提到的file.id刚好可以作为唯一标识,用来区分不同按钮的加载状态。
具体修改方案
1. 调整state结构
将原来单一的布尔状态改为存储正在加载的文件ID集合,用Set类型可以更方便地做存在判断、增删操作。
constructor(props) { super(props); this.state = { loadingFileIds: new Set() }; }
2. 修改handleFile逻辑
点击按钮时将当前文件ID加入加载集合,异步操作完成后再将ID从集合中移除,注意异常场景也要处理,避免按钮一直处于禁用状态。
async handleFile(file) { const id = file.id; // 加入当前ID到加载集合 this.setState(prev => ({ loadingFileIds: new Set(prev.loadingFileIds).add(id) })); try { // 替换为你实际的业务请求逻辑,比如文件上传/下载接口调用 const res = await yourBusinessRequest(file); if (res.statusCode === 200) { // 请求成功移除ID this.setState(prev => { const newSet = new Set(prev.loadingFileIds); newSet.delete(id); return { loadingFileIds: newSet }; }); } } catch (err) { // 请求异常也需要移除ID this.setState(prev => { const newSet = new Set(prev.loadingFileIds); newSet.delete(id); return { loadingFileIds: newSet }; }); } }
3. 调整按钮禁用判断逻辑
仅判断当前按钮对应的文件ID是否在加载集合中,来决定是否禁用当前按钮。
_renderButton(text, props) { const isFile = (props.type.toLowerCase() === 'file'); const isCurrentLoading = this.state.loadingFileIds.has(props.id); return ( <Row> {isFile && ( <Button disabled={isCurrentLoading} onClick={(e) => { e.stopPropagation(); this.handleFile(props); }} /> )} </Row> ); }
4. 用map批量渲染按钮
如果你的按钮是从文件列表批量生成的,直接遍历数组调用_renderButton即可:
render() { // 示例文件列表,替换为你实际的数据源 const fileList = [ { id: 1, type: 'file', name: '文档1.pdf' }, { id: 2, type: 'file', name: '文档2.docx' }, { id: 3, type: 'file', name: '文档3.xlsx' } ]; return ( <div> {fileList.map(file => ( <div key={file.id}> {this._renderButton(file.name, file)} </div> ))} </div> ) }
内容的提问来源于stack exchange,提问作者CodeG
相关产品推荐
相关产品推荐

