我们为什么要在没有依赖项数组的情况下使用useEffect? [英] Why would we use useEffect without a dependency array?

查看:42
本文介绍了我们为什么要在没有依赖项数组的情况下使用useEffect?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有此代码:

const App: React.FC = () => {
  const [isOpen, setIsOpen] = React.useState(true);
  const [maxHeight, setMaxHeight] = React.useState();

  const wrapper = React.useRef<HTMLDivElement>(null);
  const content = React.useRef<HTMLDivElement>(null);

  const setElementMaxHeight = () => {
    if (content && content.current) {
      setMaxHeight(isOpen ? content.current.offsetHeight : 0);
    }
  };

  useEffect(() => {
   setElementMaxHeight();

    window.addEventListener("resize", setElementMaxHeight);

    return () => {
      window.removeEventListener("resize", setElementMaxHeight);
    };
  });

  const toggle = () => {
    setIsOpen(!isOpen);
  };

  return (
    <div>
      <button onClick={toggle}>
        <span className="nominal-result__expander fa" />
      </button>
      <div
        className="nominal-results__list-wrapper"
        ref={wrapper}
        style={!!maxHeight ? { maxHeight: `${maxHeight}px` } : undefined }
      >
        <div className="nominal-results__list" ref={content} />
      </div>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

这将在每个渲染器上添加和删除事件处理程序.

This will add and remove an event handler on each render.

这一定不好吗,这实际上是从钩子中获得了什么收获吗?

Is this necessarily bad and does this actually gain anything from being a hook?

这是在代码审查中提出的,我说这很不好,因为它在每个渲染器上都添加和删除了事件侦听器.

This came up in a code review and I am saying it is bad because it adds and removes the event listener on every render.

推荐答案

对于这种 exact 案例,您是正确的,因为 undefined 是作为的依赖项传递的useEffect .

For this exact case you're right because undefined is passed as the dependencies of useEffect.

这意味着 useEffect 在每个渲染器上运行,因此事件处理程序将不必要地在每个渲染器上分离并重新附加.

This means useEffect runs on every render and thus the event handlers will unnecessarily get detached and reattached on each render.

function listener() {
  console.log('click');
}

function Example() {
  const [count, setCount] = window.React.useState(0);

  window.React.useEffect(() => {

    console.log(`adding listener ${count}`);
    window.addEventListener("click", listener);

    return () => {
      console.log(`removing listener ${count}`);
      window.removeEventListener("click", listener);
    };
  }); // <-- because we're not passing anything here, we have an effect on each render
  
  window.React.useEffect(() => {
    setTimeout(() => {
      setCount(count + 1);
    }, 1000)
  });
  
  return count;
}

window.ReactDOM.render(window.React.createElement(Example), document.getElementById('root'))

<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 id="root"></div>

但是,如果您通过传入空数组 [] 来明确声明没有依赖关系,则 useEffect 只会运行一次,因此使此模式对于事件处理程序附件而言是完全合法的.

But if you explicitly declare no dependencies by passing in an empty array [], useEffect will only run once, thus making this pattern perfectly legitimate for event handler attachment.

function listener() {
  console.log('click');
}

function Example() {
  const [count, setCount] = window.React.useState(0);

  window.React.useEffect(() => {

    console.log(`adding listener ${count}`);
    window.addEventListener("click", listener);

    return () => {
      console.log(`removing listener ${count}`);
      window.removeEventListener("click", listener);
    };
  }, []); // <-- we can control for this effect to run only once during the lifetime of this component
  
  window.React.useEffect(() => {
    setTimeout(() => {
      setCount(count + 1);
    }, 1000)
  });
  
  return count;
}

window.ReactDOM.render(window.React.createElement(Example), document.getElementById('root'))

<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 id="root"></div>

这篇关于我们为什么要在没有依赖项数组的情况下使用useEffect?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆