首页 > 解决方案 > 如果一个函数更新状态,而另一个函数随后立即访问该状态,会导致竞争条件吗?

问题描述

我有两个组件,一个是上传文件,另一个是可以提交的表单。上传者有一个上传完成的回调,表单有一个提交表单的回调。我的目标是在上传者完成上传并提交表单后向后端发出请求,而不关心先发生的情况。

我目前的解决方案是这样的:

const [isFileUploaded, setFileUploaded] = useState(false);
const [isFormSubmitted, setFormSubmitted] = useState(false);

const handleUploadFinish = ( {signedBlobId} ) => {
    // update params to be sent to the backend with the signedBlobId

    setFileUploaded(true)

    if (isFormSubmitted) {
        // make the backend call
    }
}

const handleFormSubmitted = (values) => {
    // update params to be sent to the backend with the values

    setFormSubmitted(true)

    if (setFileUploaded) {
        // make the backend call
    }
}

但是,我在有关状态的 React 文档中读到设置状态是异步操作。这让我担心,如果两个回调恰好在几乎完全相同的时间被调用,那么当它们被检查时,这两个回调可能仍然存在isFileUploaded,从而阻止后端调用的发生。isFormSubmittedfalse

这是一个有效的担忧吗?如果是这样,有什么更好的方法来处理这个问题?

标签: javascriptreactjsrace-conditionreact-state-management

解决方案


是的,按照您构建逻辑的方式,可能会有竞争条件。您应该希望您的代码具有更同步的模式。幸运的是,有一种方法可以通过集成useEffect()钩子来解决这个问题。本质上,只要您订阅的值发生更改,就会触发它。

在这种情况下,我们要验证两者isFileUploadedisFormSubmitted都是真的,只有这样我们才能进行最终的后端 API 调用。

考虑一个这样的例子:

import React, { useState, useEffect } from "react"

const myComponent = () => {

    const [isFileUploaded, setFileUploaded] = useState(false);
    const [isFormSubmitted, setFormSubmitted] = useState(false);
    const [params, setParams] = useState({})

    const handleUploadFinish = ( {signedBlobId} ) => {
        // update params to be sent to the backend with the signedBlobId
        setFileUploaded(true)
    }

    const handleFormSubmitted = (values) => {
        // update params to be sent to the backend with the values
        setFormSubmitted(true)
    }

    useEffect(() => {
        if(isFormSubmitted && isFileUploded){
           ...make backend call with updated params
        }
    }, [isFormSubmitted, isFileUploaded])

   return(
      ....
   )
}

推荐阅读