【问题标题】:What is the point of useEffect() if you don't specify a dependancy如果您不指定依赖项,那么 useEffect() 有什么意义
【发布时间】:2023-03-17 13:05:01
【问题描述】:

我在功能组件中使用反应挂钩,并且想知道当您不指定依赖项时useEffect 的用途是什么。我知道文档状态它用于副作用,但我的问题是为什么这些副作用不能在功能组件内使用纯 JS 运行?作为一个非常基本的示例,我正在使用以下代码:

import {useEffect, useState} from 'react'

function Child () {

  const [clickCount, updateCount] = useState(0)

  console.log('Run outside of useEffect')

  useEffect(()=>{
    console.log("Run inside of useEffect")
  })


  return (

    <button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
  )
}

export default Child

正如您所期望的那样,它基本上只是一个普通的 JS 函数,在每次由按钮单击引起的重新渲染时,console.log 都会被执行。

我理解为什么您可能想在如下情况下使用useEffect,如果特定情况发生变化,您只想运行useEffect

import {useEffect, useState} from 'react'

function Child () {

  const [clickCount, updateCount] = useState(0)

  console.log('Run outside of useEffect')

  //this now only runs when `someVariable` changes
  useEffect(()=>{
    
    console.log("Run inside of useEffect")
  }, [someVariable])


  return (

    <button onClick = {() => updateCount(clickCount+1)}> Child COmponent </button>
  )
}

export default Child

但这引出了一个问题,除非您将依赖矩阵指定为第二个参数,否则使用useEffect 有什么意义?用普通的JS就不能正常运行副作用吗?

【问题讨论】:

标签: javascript reactjs react-hooks use-effect


【解决方案1】:

来自docs

使用useEffect 安排的效果不会阻止浏览器更新屏幕。这使您的应用程序感觉更灵敏。大多数效果不需要同步发生。

useEffect 钩子内的代码在 DOM 更新后运行。这就是区别。

例子:

function App() {

  let [hi, setHi] = React.useState(false);
  let [inEffect, setInEffect] = React.useState(true);
  let msg = inEffect ? "useEffect (DOM will be updated immediately)" : "functional component (it will block DOM update)";
  
  return (
    <React.Fragment>
      <p>
        Long-running code is in {msg} {" "}
        <button onClick={() => (setInEffect(!inEffect), setHi(false))}>switch</button>
      </p>
      <button onClick={() => setHi(true)}>Say Hi</button>
      { hi ? <Hi {...{inEffect}}/> : null }
    </React.Fragment>
  );
}

function Hi({inEffect}) {
  !inEffect && block();
  React.useEffect(() => inEffect && block());
  return <h1>Hi!</h1>
}

function block(time = 2000) {
  const now = Date.now();
  while(now + time > Date.now());
}


ReactDOM.render(<App/>, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>

【讨论】:

    【解决方案2】:

    除非你指定依赖,否则使用 useEffect 有什么意义 矩阵作为第二个参数?

    指定依赖数组是一种优化,如果组件的不同渲染之间某些值没有改变,则告诉 React 跳过执行效果。

    使用普通JS不能正常运行副作用吗?

    useEffect钩子内部的效果相比,在顶级内部功能组件中执行的效果以不同的方式执行。

    当效果在useEffect内时:

    • 它们在浏览器绘制屏幕后执行,即在 React 将更改应用到 DOM 之后。
    • 在再次运行效果之前,useEffect 可以运行清理功能,如果提供了清理功能。
    • 指定依赖数组将允许您在每次重新渲染组件后跳过运行效果。

    由于上述几点,您总是希望在 useEffect 挂钩内执行副作用。

    就功能组件中顶层代码的影响而言,考虑以下几点:

    • 将在用户看到屏幕上的任何内容之前执行效果,即效果将在 React 更新 DOM 之前执行。

    • 在再次运行效果之前,您将没有可以执行的清理机制。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-21
      • 2021-07-04
      • 1970-01-01
      • 2018-04-10
      • 2020-12-08
      • 2012-02-14
      • 1970-01-01
      相关资源
      最近更新 更多