React中.map()内通过setState实现单条列表项下载请求独立显示加载Spinner
解决方案
1. 调整加载状态的存储结构
把原来布尔类型的全局加载状态,替换为存储正在加载的报告ID集合的状态,这样可以精准标记哪个项正在加载:
// 原来的布尔状态(可删除) // const [downloadLoadingState, setDownloadLoadingState] = useState(false) // 替换为Set结构存储正在下载的ID const [downloadingIds, setDownloadingIds] = useState<Set<string>>(new Set())
如果加载状态是从父组件通过props传递,只需把父组件的状态对应修改为上述Set结构即可。
2. 修改下载请求逻辑
请求发起时把当前报告ID加入集合,请求结束(无论成功失败)时把ID从集合移除,遵循React状态不可变更新原则:
const onDownload = (reportId: string) => { // 加入当前ID到加载集合 setDownloadingIds(prev => { const newSet = new Set(prev) newSet.add(reportId) return newSet }) backendAPIAxios.get(`/download/${reportId}`) .then((response: AxiosResponse<IDownloadResponse>) => { // 原有下载成功的处理逻辑保留 }) .catch((e: AxiosError) => { // 原有错误处理逻辑保留 }) .finally(() => { // 从加载集合移除当前ID setDownloadingIds(prev => { const newSet = new Set(prev) newSet.delete(reportId) return newSet }) }); };
3. 调整渲染判断逻辑
仅判断当前项的ID是否存在于加载集合中,即可控制单个项的加载状态显示:
<Button> {!downloadingIds.has(history.id!) ? <MSvg name='download' className={classes['svgContainerBlack']} onClick={() => onDownload(history.id!)} /> : <Tooltip title={<h1 style={{ fontSize: '17px' }}>Loading</h1>} placement="left" arrow> <CircularProgress color="inherit" /> </Tooltip> } </Button>
内容的提问来源于stack exchange,提问作者heyheyhey
相关产品推荐
相关产品推荐

