发布于 2026-01-06 0 阅读
0

react 中的 useEffect:你需要知道的一切 DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

React 中的 useEffect:你需要知道的一切

由 Mux 赞助的 DEV 全球展示挑战赛:展示你的项目!

只需理解这一点:我们使用 useEffect 在视图渲染完成后执行某些操作。

现在,让我们开始编写代码,创建一个简单的计数器来理解 useEffect:
1.gif

import {useState, useEffect} from 'react'

export default function App() {
  const [counter, setCounter] = useState(0)

  useEffect(() => {
    console.log('from useEffect...', counter)
  })

  function incrementClickHandler() {
    setCounter(counter+1)
    console.log("Inside incrementClickHandler.....", counter)
  }

  console.log('before render...', counter)

  return (
    <div className='App'>
      <h1>{counter} </h1>
      <button onClick={incrementClickHandler}>Increment</button>
    </div>
  )
}
Enter fullscreen mode Exit fullscreen mode

以下是初始渲染后的控制台输出结果(即尚未点击递增按钮): 代码或函数写在哪里并不重要,流程如下👇:
2.PNG

返回值中的 HTML将会首次渲染。然而,在渲染完成之前

console.log('before render...', counter)

,useEffect 内部的函数会立即执行,视图渲染完成后才会执行。(由于我们还没有点击递增按钮,因此 incrementClickHandler 函数不会执行。)

以下是我们第一次点击递增按钮时发生的情况:
3.PNG

下图👇是点击递增按钮后的流程图:

步骤 1:在执行 HTML 部分时,我们会遇到 onClick 事件,因此会调用 incrementClickHandler 函数。

步骤 2:请注意,`incrementClickHandler` 函数内部存在状态更新。然而,状态更新后的 `console.log` 输出的是之前的状态。这是因为,当函数内部更新状态时,实际的状态更新只能在函数外部生效,退出 `incrementClickHandler` 函数后,整个应用程序会使用新的状态重新运行。

步骤 3:虽然整个应用程序再次运行,但 useEffect 和更新状态的函数将不会执行。

步骤 4:由于整个应用程序正在运行,

console.log('before render...', counter)

因此将执行。

步骤 5:现在,视图将被渲染,递增按钮上方的数字将从 0 变为 1。

步骤 6. 现在视图已经渲染完成,useEffect 将运行。

我解释了以上所有代码,是为了让您明白 useEffect 是在视图渲染完成后运行的。

你可能会问:为什么要在视图渲染之后才调用 useState 函数?

原因如下:因为用户只关心视图,他们并不关心你的 console.log 或 localStorage(或者任何其他副作用)。因此,你应该在后端最后修改状态,并且视图应该立即反映出这个状态。如果在状态修改和视图渲染之间有任何延迟,那么这个延迟总是会拖慢渲染速度,降低用户体验。

现在你已经对 useEffect hook 有了基本的了解,让我们来了解一下它的依赖项。

依赖数组

依赖项数组是 useEffect 函数的第二个可选参数。
顾名思义,它是一个依赖项数组,当数组中的依赖项发生变化时,useEffect 函数内部的相应函数就会运行。
请参见下图:
4.PNG

让我们通过以下示例来理解上表:

import "./styles.css";
import { useEffect, useState } from 'react'

export default function App() {

  const [resource, setResource] = useState('');
  const [input, setInput] = useState('');

  useEffect(() => {console.log('See The Magic')})

  return (
    <div className="App">
      <h3>Input Element</h3>
      <input onChange={e => setInput(e.target.value)}></input>

      <h3>Buttons</h3>
      <button onClick={() => setResource('Users')}>Users</button>
      <button onClick={() => setResource('Posts')}>Posts</button>
      <button onClick={() => setResource('Comments')}>Comments</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

5.PNG

依赖项数组中只传递状态变量,useEffect 内部的函数仅在数组中提供的状态发生变化时才会运行。
我们将使用上面的示例来理解上表中给出的所有依赖项(数组值)。

情况 1:数组值:未传递值

这是默认情况,因此 useEffect 内部的函数会在每次渲染或每次状态更改后运行。

useEffect(() => {console.log('See The Magic')})
Enter fullscreen mode Exit fullscreen mode

7.gif

情况 2:数组值:传递了空数组

我在定义中已经提到,依赖数组是第二个可选参数。因此,在这种情况下,我们将在 useEffect 中添加一个空数组 ([]),其他部分保持不变。

useEffect(() => {console.log('See The Magic')}, [])
Enter fullscreen mode Exit fullscreen mode

由于我们的数组为空,并且没有传递任何状态,因此 useEffect 内部的函数只会运行一次(在初始渲染时)。
6.gif

情况 3:数组值:[状态变量 1]

我在定义中提到过,依赖数组是第二个可选参数。因此,在这个例子中,我们将在 useEffect 中添加一个包含单个状态变量的数组,看看会发生什么。

useEffect(() => {console.log('See The Magic')}, [resource])
Enter fullscreen mode Exit fullscreen mode

由于我们在数组中传递了资源值,因此 useEffect 内部的函数只会在资源值发生变化时运行。 请注意,即使状态发生了变化,当我们在输入框中输入内容时,useEffect 内部的函数也不会运行。这是因为我们只在依赖数组中传递了资源状态。
8.gif

数组值:[状态变量 2]

现在,我们不用资源状态,而是传递输入状态,看看会发生什么。

useEffect(() => {console.log('See The Magic')}, [input])
Enter fullscreen mode Exit fullscreen mode

9.gif

正如预期,当我们点击按钮时,useEffect 函数内部的函数不会运行。但是,当我们在输入框中输入内容时,它会运行。
由于我们在依赖数组中传递了输入状态,因此 useEffect 函数仅依赖于输入状态。

### 案例 4:数组值:[stateVariable1, stateVariable2]
在这种情况下,我们将把两个状态变量([resource, input])都传递给 useEffect,看看会发生什么。

useEffect(() => {console.log('See The Magic')}, [resource, input])
Enter fullscreen mode Exit fullscreen mode

7.gif

如上所示,当提供的两个状态中的任何一个发生变化时,useEffect 都会做出响应。但是,您可能会注意到它的行为与第一个条件(即未传递依赖数组)完全相同。这是因为我们只有两个状态,并且已将它们都传递到了依赖数组中。如果状态超过两个,情况可能就不同了。

还有一点需要注意的是,依赖数组中只传递状态变量(没有普通变量)。

好了,各位,希望你们理解了 useEffect。

如果您有任何疑问,请在评论区留言,我会尽快回复。

我写一篇与Web开发(主要是React)相关的文章。

如果你喜欢这篇文章,请在推特上关注我: @therajatg

如果您也使用领英,欢迎联系我https://www.linkedin.com/in/therajatg/

祝你今天过得愉快😀!

原文发布于https://rajatgupta.net/useeffect-in-react-everything-you-need-to-know

文章来源:https://dev.to/therajatg/useeffect-in-react-everything-you-need-to-know-512k