我这里有这个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
,我是否应该始终使用解构,以及为什么它不使用参数警告我。
谢谢!
当您将函数作为对象的一部分调用时,行为函数也可能取决于正在使用的对象,即使函数本身没有改变。这是一个最小的例子来说明原因
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
。
您看到的警告与 useEffect 挂钩如何处理其依赖项数组中的依赖项有关。让我们分解一下您的问题:
const { onAddedComment } = props;
useEffect(() => {
if (status === "completed" && !error)
onAddedComment();
}, [status, error, onAddedComment]);
这样,只有当 onAddedComment、状态或错误发生变化时,效果才会重新运行。
React Router 的路由参数通常不会触发相同的警告,因为它们不是标准的 React props。 React 通常关注跟踪从父组件传递的组件 props 的更改。当使用路由参数时,React Router 在内部管理这些更改,并且它们不会以相同的方式影响组件的 props。