React.js - 等待更新状态

问题描述 投票:0回答:1

我有一个父组件(

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
的更新?

reactjs react-hooks
1个回答
1
投票

这取决于定义此函数时

refs
的状态:

let updatedRefs = Object.assign({}, refs, updateRefs);
setRefs(updatedRefs);

因此,如果两个子组件都调用

updateRefs
的同一实例,那么它们都使用
refs
的同一实例。这会产生竞争条件,最后提交更新的人获胜。

状态更新是排队/批处理的,您可以使用状态设置器回调来使用队列/批处理中该点的状态值,而不是定义此函数时可用的状态值。

例如:

setRefs(prev => { let updatedRefs = Object.assign({}, prev, updateRefs); return updatedRefs; });
这样,第二个排队/批处理状态更新(竞争条件的前一个“获胜者”)将使用值 

prev

,其中也将包括来自第一个排队/批处理状态更新的更改。

© www.soinside.com 2019 - 2024. All rights reserved.