为啥将代码包装到“useEffect”中而没有第二个参数并且无需清理?

Posted

技术标签:

【中文标题】为啥将代码包装到“useEffect”中而没有第二个参数并且无需清理?【英文标题】:Why wrap code into "useEffect" without second parameter and nothing to clean up?为什么将代码包装到“useEffect”中而没有第二个参数并且无需清理? 【发布时间】:2020-05-14 19:17:53 【问题描述】:

在我见过的大多数 react 示例中,人们似乎避免将代码直接放入功能组件的主体中,而是将其包装到 useEffect(() => ...) 中。 例如。 in the official docs:

function Example() 
  const [count, setCount] = useState(0);

  useEffect(() => 
    document.title = `You clicked $count times`;
  );

  return (
    <div>
      <p>You clicked count times</p>
      <button onClick=() => setCount(count + 1)>
        Click me
      </button>
    </div>
  );

为什么这比简单地写更好:

function Example() 
  const [count, setCount] = useState(0);
  document.title = `You clicked $count times`;

  return (...);

在这两种情况下,文档标题都会在每次渲染时设置。 (我相信useEffect() 的代码是在 渲染之后执行的,但这在这个例子中似乎并不相关,对吧)

我理解useEffect() 的价值如果:

状态作为第二个参数传递,因此代码不会在每次渲染时执行,而是针对指定的状态更改执行。 我们利用了清理机制。

但是没有那个?还有理由将您的代码包装到useEffect() 中吗?

【问题讨论】:

我不是 100% 确定,但我认为普通的 const 和 useEffect 将运行相同的次数,在您的示例中使用它没有任何优势。但我可能是错的。 【参考方案1】:

回答我自己的问题。据我现在所知,没有理由或理由在代码中没有第二个参数的情况下使用 useEffect()

像reactjs.org 上的教程这样使用它的原因似乎只是出于教育原因:他们可能希望您专注于其他事情,而不是让您与第二个参数混淆。但是,这可能会导致(错误)印象,即第二个参数并不总是必需的。

再一次,这对我来说是一个教训,教程代码并不总是可以在实际项目中使用。同样在实际项目中,像 react-hooks/exhaustive-deps 这样的 lint 规则(默认包含在 create-react-app 中)会立即告诉您 useEffect() 没有第二个参数是不行的。

【讨论】:

【参考方案2】:
useEffect(() => 
    document.title = `You clicked $count times`;
  ,[count]);

代码应该是这样的,因为现在 useEffect 只会在计数状态发生变化时调用

【讨论】:

@owais 这与问题完全无关。【参考方案3】:

在此处查看官方文档about useEffect hook。 useEffect 类似于 componentDidMountcomponentDidUpdatecomponentWillUnmount 的组合。有没有提示?

【讨论】:

谢谢,我知道。但不幸的是,这并不能回答我的问题。 函数组件更像是类组件的“渲染”方法。并且 render 方法在运行时不应该有任何副作用。 “document.title”(或任何 dom 操作)是一种副作用,应在渲染中避免。 但它也不仅仅是一个类的“渲染”方法和处理状态等。另外,我的目标不是考虑有状态的功能组件如何转换为类组件,而是理解如何写得最好。

以上是关于为啥将代码包装到“useEffect”中而没有第二个参数并且无需清理?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 useEffect 之外的函数被调用,而没有依赖数组的 useEffect 内部的函数却没有?

状态在 useEffect 中没有更新,为啥?

为啥 useEffect 没有被触发?

为啥c#中的main方法总是放在类中而不是c++中

将 .so 合并到另一个 .so 中而不依赖?

为啥在构建后源代码的更改并不总是反映在机器代码中而重建工作?