我有一个父组件(
Parent
)。该组件(钩子)有一个名为 state
的 refs
变量。这个变量是一个对象,它保存了 ref
组件中使用的所有 Parent
和所有 Child
组件,如下所示:
const [refs, setRefs] = useState({
"ref1": ref1,
"ref2": ref2,
"ref3": ref3,
});
请不要问为什么。实际上当前的解决方案需要这样做。
所以
Parent
组件的代码是这样的:
export default function Parent(props) {
const ref1 = useRef(null);
const ref2 = useRef(null);
const ref3 = useRef(null);
const [refs, setRefs] = useState({
"ref1": ref1,
"ref2": ref2,
"ref3": ref3,
});
useEffect(() => {
updateRefs({
"ref1": ref1,
"ref2": ref2,
"ref3": ref3,
});
},[
ref1,
ref2,
ref3
])
function updateRefs(updateRefs) {
let updatedRefs = Object.assign({}, refs, updateRefs);
setRefs(updatedRefs);
}
return (
<div>
<Child1
updateRefs={updateRefs}
/>
<Child2
updateRefs={updateRefs}
/>
</div>
)
}
在此示例中,
Parent
组件有 3 个ref
。这些在变量refs
初始化期间直接保存,如上所示。当它们被分配给 DOM 元素时,将调用 useEffect
来更新它们。
现在谈谈我的问题。 现在
Child
通过调用函数 ref
返回它们的 updateRefs
。
当我的
Parent
组件中有超过 1 个子元素时,这就会成为一个问题。
假设 Child1
返回 ref4
和 ref5
,而 Child2
返回 ref6
和 ref7
。
当 Parent
组件渲染时,Child1
返回其 refs
。所以在Child1
更新之前,refs
的状态仍然包含ref1
、ref2
和ref3
。更新后,它还应该包含 ref4
和 ref5
。
现在,当
Child2
返回其 refs
时,尽管更新了 Child1
(= ref1
、ref2
和 ref3
),状态仍然保持不变。
因此 Child2
现在正在调用 updateRefs
,但没有之前的 Child1
更新。
最终,状态将是
ref1: ref1,
ref2: ref2,
ref3: ref3,
ref6: ref6,
ref7: ref7
而不是拥有所有
Child
updateRef
:
ref1: ref1,
ref2: ref2,
ref3: ref3,
ref4: ref4,
ref5: ref5,
ref6: ref6,
ref7: ref7
有没有办法“等待”
Child1
的更新状态,然后进行Child2
的更新?
这取决于定义此函数时
refs
的状态:
let updatedRefs = Object.assign({}, refs, updateRefs);
setRefs(updatedRefs);
因此,如果两个子组件都调用
updateRefs
的同一实例,那么它们都使用 refs
的同一实例。这会产生竞争条件,最后提交更新的人获胜。
状态更新是排队/批处理的,您可以使用状态设置器回调来使用队列/批处理中该点的状态值,而不是定义此函数时可用的状态值。
例如:
setRefs(prev => {
let updatedRefs = Object.assign({}, prev, updateRefs);
return updatedRefs;
});
这样,第二个排队/批处理状态更新(竞争条件的前一个“获胜者”)将使用值 prev
,其中也将包括来自第一个排队/批处理状态更新的更改。