React中如何为数组内被点击的项单独设置loading状态
问题根因
你当前的loading是全局布尔状态,所有列表项共享这一个状态值,所以只要触发一次加载,所有项都会匹配到state.loading === true的判断,同步显示加载状态。
解决方案
调整状态结构,不再用布尔值记录加载状态,改为存储当前正在加载的列表项的唯一标识,比如这里可以直接用车名(业务上对唯一性要求高的话也可以用专门的id字段),渲染时只给标识匹配的项显示加载状态即可。
调整后的代码示例
// 首先调整reducer的初始状态,把loading的初始值从false改成null const initialState = { // 其他原有状态 loading: null // 存储当前加载项的唯一标识,未加载时为null } // reducer里的SET_LOADING逻辑对应调整: function reducer(state, action) { switch(action.type) { case "SET_LOADING": return { ...state, loading: action.payload } // 其他原有case default: return state } } export default function App() { const [state, dispatch] = useReducer(reducer, initialState); const cars = [{ name: "Benz" }, { name: "Jeep" }, { name: "BMW" }]; // 点击时接收当前点击项的name作为参数 const handleClick = async (carName) => { // 把当前点击项的name设置到loading状态 dispatch({ type: "SET_LOADING", payload: carName }); try { // 这里放你的API调用逻辑 // await yourApiRequest() } finally { // 请求结束(无论成功失败)都把loading重置为null dispatch({ type: "SET_LOADING", payload: null }); } }; return ( <div className="App"> {cars.map(({ name }) => ( <button key={name} onClick={() => handleClick(name)}> {/* 只有当前项的name和存储的loading标识相等时才显示加载 */} {state.loading === name ? "Loading..." : name} </button> ))} </div> ); }
可选优化
如果你的业务存在多个项同时加载的场景,可以把loading改成Set结构,存储所有正在加载的项的标识,判断的时候用state.loading.has(name)即可。
内容的提问来源于stack exchange,提问作者krsna
相关产品推荐
相关产品推荐

