我有一个使用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中具有此属性(使用useRef创建optionElement):
useEffect(() => {
const elementInfo = optionElement.current.getBoundingClientRect();
props.reportBoundingRect(elementInfo.width, elementInfo.left); });
这只是代码的简化版本,我添加了此const newInfo来收集此新的信息数组,没有它,宽度和剩余信息将从内存中丢失,因为setState是异步的并等待更多更改(但是当它真正被调用时,该信息将不再存在,并且在该数组中变得不确定。
我在有状态的组件中尝试了此操作,但是componentDidMount和setState的结果以及所有内容都是相同的,我真的很想获得一些有关如何实现上述行为的指针
非常感谢您的帮助
答案 0 :(得分:0)
因此,代码中的问题是子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仅在初始渲染(或某些更改)时起作用
useEffect(() => {
const elementInfo = optionElement.current.getBoundingClientRect();
props.reportBoundingRect(elementInfo.width, elementInfo.left);
}, []);