useEffect中的props在其依赖数组中时,每当组件重新渲染时是否会重新运行?

huangapple go评论67阅读模式
英文:

Does useEffect with props in its dependency array rerun whenever the component renders?

问题

如在React文档的useEffect部分所示,通常应该在useEffect的依赖数组中包含props

import { useEffect } from 'react';
import { createConnection } from './chat.js';

function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => {
      connection.disconnect();
    };
  }, [serverUrl, roomId]);
  // ...
}

我在某处读到,传递给React组件的props对象在每次渲染时都会发生变化。即使对象的属性(键和值)可能相同,但在每次渲染之间它不是相同的对象。

在上面的示例中,假设roomId实际上是一个对象(而不仅仅是一个数字),那么即使roomId对象的键和值没有更改,useEffect是否不会在每次渲染时重新运行?

附注:最终目标是理解上述问题,以便只在解构后的props对象的键和值发生变化时运行效果。

英文:

As seen under the useEffect section of the React docs, props should generally be included in useEffect's dependency array:

import { useEffect } from 'react';
import { createConnection } from './chat.js';

function ChatRoom({ roomId }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
    const connection = createConnection(serverUrl, roomId);
    connection.connect();
    return () => {
      connection.disconnect();
    };
  }, [serverUrl, roomId]);
  // ...
}

I have read somewhere that the props object passed to a react component always changes on each render. I.e. it is not the same object from one render to the next, even though the object's properties (keys and values) may be the same.

In the example above, assuming roomId was actually an object (and not just a number), does the useEffect not re-run on every render, even if roomId object's keys and values did not change?

Side note: As an end goal, I would like to understand the above so I can run an effect only if my destructured props object's keys and values changed.

答案1

得分: 1

您的道具对象可能会在每次渲染时更改,但在确定何时触发效果钩子时,将比较效果钩子依赖中使用的值,而不是它们可能是一部分的任何对象。

演示....

const roomId = { id: 123 };
const props1 = { roomId };
const props2 = { roomId };

console.log("props 相等吗?", props1 === props2); // false
console.log("roomId 相等吗?", props1.roomId === props2.roomId); // true

只要在每个渲染周期中使用的相同值(或对象引用)存在,您的效果钩子就不会重新运行。

这就是为什么 react-hooks/exhaustive-deps ESLint 规则特别提到...

但是,'props' 会在任何 prop 更改时发生更改,因此首选的修复方法是在 useEffect 调用之外解构 'props' 对象,并在 useEffect 中引用那些特定的 props。

如果您不能保证对象的相等性,那么我建议拿出您可以识别的任何属性

function ChatRoom({ roomId: { id } }) {
  const [serverUrl, setServerUrl] = useState('https://localhost:1234');

  useEffect(() => {
    // ...
  }, [serverUrl, id]);
}
英文:

While your props object might change with each render, the values used in the effect hook dependencies are compared when determining when to trigger, not any objects they might be part of.

To demonstrate....

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const roomId = { id: 123 };
const props1 = { roomId };
const props2 = { roomId };

console.log(&quot;props equal?&quot;, props1 === props2); // false
console.log(&quot;roomId equal?&quot;, props1.roomId === props2.roomId); // true

<!-- end snippet -->

So as long as the same value (or object reference) used in your hook dependencies is present in each render cycle, your effect hook will not re-run.

This is why the react-hooks/exhaustive-deps ESLint rule has a special mention...

> However, 'props' will change when any prop changes, so the preferred fix is to destructure the 'props' object outside of the useEffect call and refer to those specific props inside useEffect.eslint(react-hooks/exhaustive-deps)

If you cannot guarantee object equality, then I would recommend pulling out whatever identifying properties you can

function ChatRoom({ roomId: { id } }) {
  const [serverUrl, setServerUrl] = useState(&#39;https://localhost:1234&#39;);

  useEffect(() =&gt; {
    // ...
  }, [serverUrl, id]);

huangapple
  • 本文由 发表于 2023年2月10日 12:18:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/75406903.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定