useEffect 依赖数组的问题
Posted
技术标签:
【中文标题】useEffect 依赖数组的问题【英文标题】:Issue with useEffect dependency array 【发布时间】:2021-10-11 17:44:49 【问题描述】:我的项目正在使用 useState 和 useEffect 挂钩从 API 获取数据。该请求在我的本地主机上正常工作和呈现,但我收到以下警告:
React Hook useEffect 缺少一个依赖项:'fetchData'。要么包含它,要么移除依赖数组。
警告阻止我部署我的项目。我已经尝试将“fetchData”添加到数组以及完全删除数组。两者都会导致错误。
将 'fetchData' 添加到数组会导致另一个警告:
'fetchData' 函数使 useEffect Hook(第 31 行)的依赖关系在每次渲染时都发生变化。将它移到 useEffect 回调中。或者,将 'fetchData' 的定义包装在它自己的 useCallback() Hook 中。
删除数组会导致此控制台错误:
CORS 策略阻止了从源“http://localhost:3000”获取的访问权限:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明的响应满足您的需求,请将请求的模式设置为“no-cors”以获取禁用 CORS 的资源。
我只需要在加载时渲染一次状态。这是我的代码:
export function Product(Inventory_ID, Cost)
const [ data, setData ] = useState("");
const [ centers, setCenters ] = useState([]);
const fetchData = async () =>
try
const response = await fetch(`$API_ENDPOINT$Inventory_ID`, REQUEST_OPTIONS);
const data = await response.json();
setData(data);
const centers = await data.fulfillable_quantity_by_fulfillment_center;
setCenters(centers);
catch (e)
console.error(e);
useEffect(() =>
fetchData();
, []);
// Currency formatter
const formatter = new Intl.NumberFormat('en-US',
style: 'currency',
currency: 'USD',
maximumFractionDigits: 0,
)
return (
<div className="card">
<h2>data.name</h2>
<h3>Total Onhand Quantity</h3>
<p>data.total_onhand_quantity</p>
<h3>Total Onhand Value</h3>
<p>formatter.format(data.total_onhand_quantity * Cost)</p>
<h3>Quantity by Fulfillment Center</h3>
centers.map((center) =>
return (
<div>
<h4 key=center.name>center.name</h4>
<p key=center.onhand_quantity>`Onhand Quantity: $center.onhand_quantity`</p>
<p key=center.awaiting_quantity>`Awaiting Quantity: $center.awaiting_quantity`</p>
</div>
);
)
<div>
</div>
</div>
)
知道我在哪里出错以及如何解决吗?
非常感谢。
【问题讨论】:
【参考方案1】:不确定你之前做了什么来得到这些错误,但你现在的代码看起来是正确的。您现在的问题是,无论 API_ENDPOINT
是什么都没有启用 CORS。这意味着服务器没有将您的域列入“您可以发出请求”的白名单,因此当它访问您的浏览器时,您的浏览器会通过使您的 fetch 调用无效来“保护”您。
为了解决这个问题,您需要在 API 服务器上启用 CORS,并且需要将运行 UI 的域列入白名单。或者您可以创建自己的 API 并从那里提取数据,然后您可以从他们的 API 服务器端获取数据,这样您的浏览器就不会 CORS 拒绝您。
旁注,我不确定我是否正确,但这可能会给您带来问题:
setData(data);
const centers = await data.fulfillable_quantity_by_fulfillment_center;
setCenters(centers);
或者至少它只是非常未优化。 React 将设置状态,重新渲染组件,同时等待第二次 fetch 调用完成,然后再次设置状态并重新渲染。
改为进行所有 fetch 调用,然后设置所有状态,以便 react 可以通过批量更新渲染组件。
【讨论】:
感谢您的回复。我不控制 API 服务器,但我会寻求支持。我仍然不明白为什么会有这么多请求发生,每个唯一的 Inventory_ID 应该只有一个请求,我的应用程序有六个。知道如何将请求限制为仅加载一次吗? 您还可以创建自己的 API 服务器端并在那里获取数据,这样您就不会使 CORS 失效,CORS 只是一个浏览器策略,所以如果您从他们的 API 服务器端获取然后获取从您自己的 API 它将起作用。此外,由于数据返回后状态更新,您的组件一直在重新渲染。您应该在一个地方进行所有状态更新,而不是在每个数据返回之后,您还应该使用useEffect
返回数组来保持状态,即useEffect(() => , [inventoryId])
,以防止它一遍又一遍地呈现。
谢谢。我是一名新开发人员,因此创建自己的 API 服务器端远远超出了我的能力。任何机会您都可以向我展示您的意思是“此外,一旦数据返回,由于状态更新,您的组件一直在重新渲染。您应该在一个地方完成所有状态更新,”我将如何在我的代码中完成此操作?此外,我尝试在 useEffect 依赖数组中包含 prop 'Inventory_ID',但收到关于它缺少依赖项 'fetchData' 的相同警告。我知道我需要更好地了解状态和挂钩的工作原理,因此感谢您的帮助!
每次调用setSomething
都会触发组件的重新渲染,所以如果你等待数据,然后设置它,然后等待数据,然后设置它,你在重复重新渲染组件并在每次渲染时触发useEffect
。取而代之的是获取您想要的所有数据,然后设置所有状态。除此之外,错误告诉您将fetchData
函数移动到useEffect
中,所以这样做。此外,fetchData
不应添加到数组中,data
和 centers
应该。
谢谢!我删除了centers
以简化问题,然后将我的fetchData
函数移到useEffect
中。依赖数组调用Inventory_ID
(就像您最初建议的那样)而不是data
,所以我将Inventory_ID
添加到数组中,它现在可以正常工作而没有任何警告。现在我只需要返回并弄清楚如何在不触发重新渲染的情况下添加回centers
。我遇到的问题是 centers
是一个数组,所以我不确定如何在同一个 setState
中处理它以上是关于useEffect 依赖数组的问题的主要内容,如果未能解决你的问题,请参考以下文章
为啥在组件加载时不调用 useEffect(()=...,[]) ?
为啥 useEffect 之外的函数被调用,而没有依赖数组的 useEffect 内部的函数却没有?