React项目中如何仅点击按钮后显示Loading?(useReducer方案)
问题
在React项目中,有一个按钮点击后发起API请求,目前存在两个问题:
- 页面首次加载时,未点击按钮就已显示“Loading”文本
- 更新代码后出现新问题:当设置loading为true时,数据面板会消失
需求:
- 实现仅点击按钮后才显示“Loading”(因某些原因无法直接使用setLoading状态)
- 通过useReducer处理API请求成功、失败的不同逻辑
解决方案(基于useReducer实现)
使用useReducer管理请求的全生命周期状态(初始、加载、成功、错误),根据不同状态渲染对应内容:
import React, { useReducer, useEffect } from 'react'; import axios from 'axios'; // 初始状态定义 const initialState = { status: 'idle', // idle:初始状态, loading:加载中, success:请求成功, error:请求失败 post: null, error: null }; // 状态处理reducer函数 function requestReducer(state, action) { switch (action.type) { case 'REQUEST_START': return { ...state, status: 'loading', error: null }; case 'REQUEST_SUCCESS': return { ...state, status: 'success', post: action.payload }; case 'REQUEST_ERROR': return { ...state, status: 'error', error: action.payload }; default: return state; } } export function App(props) { const [state, dispatch] = useReducer(requestReducer, initialState); useEffect(() => { console.log(state.post); }, [state.post]); const handleLoadData = () => { dispatch({ type: 'REQUEST_START' }); axios.get('https://jsonplaceholder.typicode.com/todos/1') .then((response) => { dispatch({ type: 'REQUEST_SUCCESS', payload: response.data }); }) .catch((err) => { dispatch({ type: 'REQUEST_ERROR', payload: err.message }); }); }; return ( <div className='App'> <button onClick={handleLoadData}>Load data</button> {state.status === 'loading' && <p>Loading</p>} {state.status === 'success' && <Databoard post={state.post} />} {state.status === 'error' && <p>请求错误:{state.error}</p>} </div> ); } const Databoard = (props) => { const { post } = props; return ( <ul> <li>{post.userId}</li> <li>{post.id}</li> <li>{post.title}</li> </ul> ); }
关键说明
- 控制Loading显示:初始状态为
idle,此时不会渲染Loading;只有点击按钮触发REQUEST_START动作后,状态切换为loading,才会显示Loading文本,解决了未点击就加载的问题。 - 请求状态处理:
- 请求成功时,状态切换为
success,渲染数据面板Databoard - 请求失败时,状态切换为
error,显示错误提示信息
这种明确的状态划分,避免了原代码中加载时数据面板消失的问题,每个状态对应独立的渲染逻辑,逻辑清晰且不易出错。
- 请求成功时,状态切换为
内容的提问来源于stack exchange,提问作者Ae Leung
相关产品推荐
相关产品推荐

