React - 添加 props.something 作为 useEffect 的依赖项

问题描述 投票:0回答:2

我这里有这个useEffect代码:

useEffect(() => {
    if (status === "completed" && !error) 
      props.onAddedComment();
  }, [status,error,props.onAddedComment]);

但是我在终端中收到此警告: React Hook useEffect 缺少依赖项:“props”。包含它或删除依赖项数组。但是,当 any prop 更改时,'props' 也会更改,因此首选修复方法是在 useEffect 调用之外解构 'props' 对象,并引用 useEffect

内的那些特定 props

如果我传递

props.onAddedComment
而不是整个 props 对象,为什么需要使用解构?即使我添加了
.onAddedComment
,它仍然会引用整个道具吗?

我对使用

params
有同样的问题,在这段代码中:

useEffect(() => {
    sendRequest(params.quoteId);
  }, [params.quoteId, sendRequest]);

我在这里没有收到此警告,为什么?

简而言之,我的问题是,即使我在 props 之后添加

.something
,我是否应该始终使用解构,以及为什么它不使用参数警告我。

谢谢!

javascript reactjs react-hooks react-props destructuring
2个回答
3
投票

感谢Andrius找到了这个。请参阅此处

当您将函数作为对象的一部分调用时,行为函数也可能取决于正在使用的对象,即使函数本身没有改变。这是一个最小的例子来说明原因

useEffect(() => {
  obj.fn();
}, [obj.fn]);

可能是个问题:

const Child = ({ obj }) => {
  React.useEffect(() => {
    obj.fn();
  }, [obj.fn]);
  return null;
};
const App = () => {
  console.log('App rendering');
  const [count, setCount] = React.useState(0);
  // This fn is stable across renders
  const [fn] = React.useState(() => function() { console.log('count is', this.count); });
  React.useEffect(() => {
    setTimeout(() => {
      console.log('Calling setCount; expecting obj.fn to be called again');
      setCount(count + 1);
    }, 1000);
  }, []);
  return <Child obj={{ count, fn }} />
};

ReactDOM.render(<App />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>

exhaustive-deps 的目的是让您在回调内的任何内容发生变化时调用效果回调。因为从理论上讲,对对象的更改可能会导致执行的逻辑发生更改如果该对象有方法,则该对象本身应该添加到依赖项数组中。

这不会产生错误:

useEffect(() => {
  sendRequest(params.quoteId);
}, [params.quoteId, sendRequest]);

因为

quoteId
不是您正在调用的函数;与我上面的代码片段和您的原始代码相比,
this
params
并不重要,在这种情况下,
this
props
理论上可能很重要。

如果你这样做了

useEffect(() => {
  sendRequest(params.getQuoteId());
}, [params.getQuoteId, sendRequest]);

这会产生警告,因为现在

getQuoteId
的调用取决于
params
是什么。

从对象中删除函数并将函数放入独立标识符中也会消除警告,因为将函数作为独立标识符而不是对象的一部分调用会消除函数对对象的可能依赖关系 -

this
函数内部不再引用对象,而是
undefined

一种思考方式是,当您将函数作为对象的一部分调用时,对象本身将作为隐藏的附加参数传递给函数,就像函数内部的

this
一样。

这个:

useEffect(() => {
  obj.fn();
}, [obj.fn]);

就像在做

const { obj } = fn;
useEffect(() => {
  fn.call(obj)
}, [fn]);

这显然缺少

obj
作为依赖项 - 即使
fn
的实现根本不考虑其
this


-2
投票

您看到的警告与 useEffect 挂钩如何处理其依赖项数组中的依赖项有关。让我们分解一下您的问题:

  1. 关于道具:您看到的警告表明您应该 解构您在 useEffect 中使用的特定 prop 而不是在依赖数组中包含 props。这是 因为,在 React 中,当你在依赖数组中包含 props 时, 这意味着只要有任何道具,效果就会重新执行 改变,这可能不是你想要的。如果你只想要效果 要在 props.onAddedComment 更改时运行,您应该解构 该特定的 prop 并将其包含在依赖项数组中,例如 这个:
const { onAddedComment } = props;

useEffect(() => {
  if (status === "completed" && !error) 
    onAddedComment();
}, [status, error, onAddedComment]);

这样,只有当 onAddedComment、状态或错误发生变化时,效果才会重新运行。

  1. 关于参数: 您没有收到警告的原因 params 是您看到的警告特定于处理 道具。在 params 的情况下,它很可能是一条数据 来自 React Router 或类似的路由库,React 是 旨在以不同的方式处理它。

React Router 的路由参数通常不会触发相同的警告,因为它们不是标准的 React props。 React 通常关注跟踪从父组件传递的组件 props 的更改。当使用路由参数时,React Router 在内部管理这些更改,并且它们不会以相同的方式影响组件的 props。

© www.soinside.com 2019 - 2024. All rights reserved.