我有一个父功能组件,它使用 useState 钩子来设置状态(这个问题在钩子中的事实应该是无关紧要的,因为我在使用类组件时遇到了相同的行为),它需要设置有关它在渲染子级时收集的一些信息的状态,但是当设置状态时,它会再次重新渲染子级,从而导致无限循环
export const SomeConst = (props) => {
const [information, setInformation] = useState([]);
const newInfo = []
const reportBoundingRectWithIndex = (index) => {
return (width, left) => {
newInfo[index] = { width, left };
setInformation(newInfo);
};
};
return (
{children.map(child => (
<ChildComponent
reportBoundingRect={reportBoundingRectWithIndex(index)}
/>
))}
)}
渲染的子组件在useEffect中具有以下内容(optionElement是使用useRef创建的):
useEffect(() => {
const elementInfo = optionElement.current.getBoundingClientRect();
props.reportBoundingRect(elementInfo.width, elementInfo.left); });
这只是代码的简化版本,我添加了这个 const newInfo 来收集这个新的信息数组,没有它,宽度和左侧信息就会从内存中丢失,因为 setState 是异步的,需要等待更多更改(但是当它实际被调用时,此信息不再存在,并且在这个数组中变得未定义)
我在有状态组件中尝试过这个,但是组件DidMount和setState的结果并且一切都是一样的,我真的很想得到一些关于如何实现所述behvaiour的指针
任何帮助都非常感谢
所以代码中的问题是不应该在每次更新时调用子useEffect
,否则这将导致无限循环,因为内部useEffect
你调用一个更新状态并导致重新渲染的父函数,再次触发 useEffect
export const SomeConst = (props) => {
const [information, setInformation] = useState([]);
const newInfo = []
const reportBoundingRectWithIndex = (index) => {
return (width, left) => {
newInfo[index] = { width, left };
setInformation(newInfo);
};
};
return (
{children.map(child => (
<ChildComponent
reportBoundingRect={reportBoundingRectWithIndex(index)}
/>
))}
)}
)
}
在子调用中使用仅在初始渲染(或某些更改)上生效
useEffect(() => {
const elementInfo = optionElement.current.getBoundingClientRect();
props.reportBoundingRect(elementInfo.width, elementInfo.left);
}, []);