React删除Region后重载数据触发Hook错误及map函数异常
问题分析与解决方案
核心问题
你遇到的两个错误根源如下:
- Invalid hook call错误:
LoadRegionsAll是一个自定义Hook(内部使用了useState、useEffect),根据React Hook规则,Hook只能在组件顶层作用域调用,不能在事件回调(比如deleteRegion)中执行,否则会触发该异常。 - map is not a function错误:你之前把
regionsData初始化为对象{},而对象没有map方法,改成初始化为空数组[]即可解决。
修复步骤
1. 重构LoadRegionsAll为普通异步函数
把原来的自定义Hook改成纯数据请求函数,这样可以在任何异步场景下调用:
// LoadRegionsAll.js const LoadRegionsAll = async () => { const url = global.config.URL.Path + `/region`; try { const response = await fetch(url, { headers: { "Cache-Control": "no-cache", }, }); if (!response.ok) { throw new Error(`HTTP错误:状态码 ${response.status}`); } const actualData = await response.json(); return actualData.result; } catch (err) { console.error("加载区域数据失败:", err.message); throw err; // 抛出错误让调用者处理 } }; export default LoadRegionsAll;
2. 修改Regions组件,用状态管理数据并处理删除逻辑
在组件中用useState维护区域数据,初始化时加载数据,删除成功后重新请求并更新状态:
// Regions.js import { useState, useEffect } from "react"; import Swal from "sweetalert2"; import "../../../config"; import "./Regions.css"; import LoadRegionsAll from "./LoadRegionsAll"; function Regions() { const [error, setError] = useState(""); const [regionsData, setRegionsData] = useState([]); // 初始化为空数组,避免map报错 // 初始化加载区域数据 useEffect(() => { const fetchInitialData = async () => { try { const data = await LoadRegionsAll(); setRegionsData(data); } catch (err) { setError(err.message); } }; fetchInitialData(); }, []); async function deleteRegion(Region) { const confirmResult = await Swal.fire({ title: `确定要删除:\n"${Region.regionName}"?`, showCancelButton: true, confirmButtonText: "删除", cancelButtonText: "取消" }); if (confirmResult.isConfirmed) { try { // 执行删除请求 const deleteRes = await fetch(global.config.URL.Path + `/Region/${Region.id}`, { method: "DELETE", }); if (!deleteRes.ok) { throw new Error(`删除失败:状态码 ${deleteRes.status}`); } // 删除成功后重新加载数据 const updatedRegions = await LoadRegionsAll(); setRegionsData(updatedRegions); Swal.fire("已删除", `${Region.regionName} 成功删除`, "success"); } catch (err) { setError(err.message); Swal.fire("错误", err.message, "error"); } } } // 渲染区域列表(示例) return ( <div className="Regions"> {error && <div className="error提示">{error}</div>} <div className="region-list"> {regionsData.map(region => ( <div key={region.id} className="region-item"> <span>{region.regionName}</span> <button onClick={() => deleteRegion(region)}>删除</button> </div> ))} </div> </div> ); } export default Regions;
关键说明
- 把Hook改成普通异步函数后,既复用了数据请求逻辑,又避免了Hook规则冲突。
- 用
useState管理regionsData,更新状态时会自动触发组件重新渲染,展示最新数据。 - 初始状态设为空数组,确保
map方法能正常执行,避免类型错误。
内容的提问来源于stack exchange,提问作者Technology 2023
相关产品推荐
相关产品推荐

