UseEffect不是由依赖项触发的吗?

时间:2020-10-28 00:38:23

标签: javascript reactjs

有人可以帮助我吗?我真的很感激:) 这里的问题是,当宽度和高度改变时,UseEffect不会再次运行。 这是一个正在调整大小的文本区域...

const [elem, setElem] = useState<HTMLElement>(document.createElement('textarea'))
const width = window.getComputedStyle(elem, null).getPropertyValue("width");
const height = window.getComputedStyle(elem, null).getPropertyValue("height");

   useEffect(() => {
      setElem(document.getElementById("email") as HTMLElement) 
      console.log(width, height)
   },[elem, width, height])

2 个答案:

答案 0 :(得分:0)

使用useState设置宽度和高度。

const [width, setWidth] = useState(undefined);
const [height, setHeight] = useState(undefined);


useEffect(() => {
  const getWidth = () => window.getComputedStyle(elem, null).getPropertyValue("width");

  const getHeight = () => window.getComputedStyle(elem, null).getPropertyValue("height");
  const resizeListener = () => {
      setWidth(getWidth())
      setHeight(getHeight())
    };

  window.addEventListener('resize', resizeListener);

  resizeListener();
  // Don't foget cleanup!
  return () => window.removeEventListener('resize', resizeListener);
  // There's a dependency on the element, so if that changes, re-run the effect
}, [elem])


附加大小调整事件侦听器,并使用setWidth和setHeight更新宽度和高度。

答案 1 :(得分:0)

@ William-wang有一个正确的主意。您的代码不会重新触发效果,因为值永远不会改变,除非在代码由于其他原因而重新渲染时可能会发生变化。

虽然他的方法是在窗口上使用调整大小的侦听器来更新宽度和高度,但只有在窗口大小改变时才会发生这种情况。

我已经修改了代码以使用较新的Resize Observer api。在How to detect DIV's dimension changed?中有更多详细信息。

通过这种方式,可以获取准确且最新的尺寸更改。这种方法的唯一问题是older browsers don't support it。尽管目前似乎所有现代主流浏览器都支持它。

Context
const { useState, useEffect, useRef } = React;
function Example() {
  const elemRef = useRef(null);
  const [width, setWidth] = useState(undefined);
  const [height, setHeight] = useState(undefined);

  useEffect(() => {
    if (!elemRef.current) {
      return;
    }
    const resizeListener = () => {
      setWidth(elemRef.current.offsetWidth);
      setHeight(elemRef.current.offsetHeight);
    };
    const observer = new ResizeObserver(resizeListener);
    observer.observe(elemRef.current);
    // Don't foget cleanup!
    return () => observer.disconnect();
  }, []);

  return (
    <div>
      width: {width}
      <br />
      height: {height}
      <br />
      <textarea ref={elemRef} />
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));