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

使用React自定义Hook更新UI时删除用户重拉列表及加载态处理问题

问题根因

  • 违反React Hook调用规则:Hook仅可在组件顶层作用域或自定义Hook内部调用,你在deleteUser事件回调中调用useFetch的写法本身不符合规范,自然无法拿到回调外的状态。
  • 现有useFetch设计不完善:未将内部的fetchData方法暴露给外部调用方,无法手动触发数据重新拉取。同时useCallback的依赖项缺少params,参数更新时无法触发请求更新。
  • 删除操作没有独立的状态管理:删除属于提交类操作,和拉取列表的查询类操作要分开管理状态,才能在渲染层读取删除中的状态展示加载器。

修复后的代码

调整useFetch实现

import { useState, useCallback, useEffect } from 'react';

export interface APIStatus {
  status: 'loading' | 'error' | 'done';
}

// 泛型支持自定义返回数据类型
export const useFetch = <T = any>(api: (params: any) => Promise<{data: T}>, params: any) => {
  const [data, setData] = useState<T[]>([]);
  const [apiStatus, setApiStatus] = useState<APIStatus>({ status: 'loading' });
  const [isSignedIn] = getSignInStatus();

  // 依赖项补上params,参数变化时自动更新请求方法
  const fetchData = useCallback(async () => {
    setApiStatus({ status: 'loading' });
    try {
      const {data} = await api(params);
      setData(data);
      setApiStatus({ status: 'done' });
    } catch (err) {
      setApiStatus({ status: 'error' });
    }
  }, [api, params]);

  useEffect(() => {
    if (isSignedIn) fetchData();
  }, [isSignedIn, fetchData]);

  // 暴露手动刷新方法给外部
  return { apiStatus, data, refetch: fetchData };
};

调整App组件实现

// App.tsx
import { useState } from 'react';

export const App: React.FC = () => {
  const { apiStatus: listStatus, data: userList, refetch: refetchUsers } = useFetch(apis.fetchUsers, "limit=100");
  // 独立维护删除操作的状态
  const [deleteStatus, setDeleteStatus] = useState<APIStatus>({ status: 'done' });

  const deleteUser = async (id: string) => {
    setDeleteStatus({ status: 'loading' });
    try {
      await apis.deleteUser(`id=${id}`);
      // 删除成功后重新拉取最新用户列表
      await refetchUsers();
      setDeleteStatus({ status: 'done' });
    } catch (err) {
      setDeleteStatus({ status: 'error' });
    }
  }

  return(
    <>
      {/* 列表加载/删除操作中都可以展示加载器,可按需调整为单条记录的加载效果 */}
      {listStatus.status === 'loading' || deleteStatus.status === 'loading' ? <ShowLoader /> : 
        userList.map(user => <div key={user.id} onClick={() => deleteUser(user.id)}> {user.name} </div>)
      }
    </>
  )
}

实现说明

  • 调整后的useFetch主动暴露refetch方法,删除操作成功后直接调用即可拉取最新的用户列表
  • 单独为删除操作维护deleteStatus状态,渲染层可以直接读取该状态判断是否需要展示加载器,也可拓展为单条记录的删除中状态,仅给被点击的用户条目加加载效果
  • 补全了useFetch内部useCallback的依赖项,避免参数更新后请求不生效的隐藏问题

内容的提问来源于stack exchange,提问作者newbie

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 05:27:04