You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React项目中如何仅点击按钮后显示Loading?(useReducer方案)

问题

在React项目中,有一个按钮点击后发起API请求,目前存在两个问题:

  • 页面首次加载时,未点击按钮就已显示“Loading”文本
  • 更新代码后出现新问题:当设置loading为true时,数据面板会消失

需求:

  1. 实现仅点击按钮后才显示“Loading”(因某些原因无法直接使用setLoading状态)
  2. 通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 10:18:18