gpt4 book ai didi

reactjs - useLayoutEffect、useRef 超出了最大更新深度

转载 作者:行者123 更新时间:2023-12-05 03:50:12 31 4
gpt4 key购买 nike

我有以下组件:

// component.js
import React from 'react';
import useComponentSize from 'useComponentSize';

const component = () => {
const [comSize, comRef] = useComponentSize();

return (
<div style={{width: '100%'}} ref={comRef}>
<p>hi</p>
</div>
);
};

它正在使用 useComponentSize,这是我制作的一个钩子(Hook):

// useComponentSize.js
import {
useRef,
useState,
useLayoutEffect,
} from 'react';

const useComponentSize = () => {
const [size, setSize] = useState({
width: 0,
height: 0,
});
const resizeRef = useRef();

useLayoutEffect(() => {
setSize(() => ({
width: resizeRef.current.clientWidth,
height: resizeRef.current.clientHeight,
}));
});

return [size, resizeRef];
};

export default useComponentSize;

但由于我无法解决的原因,它总是超过最大更新深度。我试过让 useLayoutEffect 依赖于 resizeRef,我认为这会起作用,但后来它不会再次更新(这正是我应该期望的引用工作)。

我应该怎么做才能使其正常工作,最重要的是为什么上述会导致无限循环?


编辑:第二次尝试使用事件监听器,仍然失败。我在这里缺少什么概念?

// component.js
import React, { useRef } from 'react';
import useComponentSize from 'useComponentSize';

const component = () => {
const ref = useRef();
const [comSize] = useComponentSize(ref);

return (
<div style={{width: '100%'}} ref={ref}>
<p>hi</p>
</div>
);
};
import {
useRef,
useState,
useLayoutEffect,
} from 'react';

const useComponentSize = (ref) => {
const [size, setSize] = useState();

useLayoutEffect(() => {
const updateSize = () => {
setSize(ref.current.clientWidth);
}

ref.current.addEventListener('resize', updateSize);
updateSize();

return () => window.removeEventListener('resize', updateSize);
}, []);

return [size];
};

export default useComponentSize;

上面的编辑是基于这个 useWindowSize钩子(Hook),效果很好(我目前正在使用它作为替代品,尽管我宁愿让上面的东西继续工作,尤其是想知道为什么它不起作用)。


对我试图实现的目标的一个小解释,因为它之前没有明确说明:我希望状态 size 在引用组件的大小发生变化时更新。也就是说,如果窗口调整大小,而组件保持相同大小,则它不应更新。但是,如果组件大小确实发生了变化,则 size 状态应该更改值以反射(reflect)这一点。

最佳答案

您的代码陷入无限循环,因为您没有将依赖项数组传递给 useEffectLayout Hook 。

您实际上根本不需要使用 useEffectLayout Hook 。您可以使用 ResizeObserver API 观察 DOM 元素的变化。 .

P.S:虽然 OP 的问题已经通过问题下评论之一中发布的演示解决了,但我发布了一个答案,供将来可能会查看此问题的任何人使用。

示例:

const useComponentSize = (comRef) => {
const [size, setSize] = React.useState({
width: 0,
height: 0
});

React.useEffect(() => {
const sizeObserver = new ResizeObserver((entries, observer) => {
entries.forEach(({ target }) => {
setSize({ width: target.clientWidth, height: target.clientHeight });
});
});
sizeObserver.observe(comRef.current);

return () => sizeObserver.disconnect();
}, [comRef]);

return [size];
};

function App() {
const comRef = React.useRef();
const [comSize] = useComponentSize(comRef);

return (
<div>
<textarea ref={comRef} placeholder="Change my size"></textarea>
<h1>{JSON.stringify(comSize)}</h1>
</div>
);
}

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

关于reactjs - useLayoutEffect、useRef 超出了最大更新深度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63560033/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com