Search code examples
reactjstsx

Specify async function in React prop expression


I have a Button which is disabled depending on an isSubmitDisabled function which is defined as async because it has an async part.

<Button type="button" disabled={isSubmitDisabled()}>Submit</Button>

const isSubmitDisabled = async () => {
    let result1 = await validatePart1(..);
    //...
    return finalResult ? true : false;
}

The validation works, but I can't use the prop expression syntax above for disabled=.

If I do disabled={isSubmitDisabled()}>

error: Type 'true | Promise' is not assignable to type 'boolean | undefined'. Type 'Promise' is not assignable to type 'boolean | undefined'.ts(2322)

If I do disabled={await isSubmitDisabled()}>

error: 'await' expressions are only allowed within async functions and at the top levels of modules

If I do a wrapper function per this example:

disabled = {
  (async () => {
    await isSubmitDisabled()
  })()
}

error: Type 'Promise' is not assignable to type 'boolean | undefined'.


Solution

  • You can't synchronously get a value from an asynchronous operation.

    Use a state value to drive the UI, and update that state value from the asynchronous operation. For example, consider a simple boolean state:

    const [disableSubmit, setDisableSubmit] = useState(true);
    

    Use that value to drive the button:

    <Button type="button" disabled={disableSubmit}>Submit</Button>
    

    Then you can update that state value from the asynchronous operation. When/where that operation is invoked is up to you, in this case I'm just adding it to a useEffect which is executed once when the component first loads:

    useEffect(() => {
      (async () => {
        let result1 = await validatePart1(..);
        //...
        setDisableSubmit(finalResult ? true : false);
      })();
    }, []);
    

    Depending on the structure of what you're building, you may invoke this operation at a different time or even at multiple times. But however you structure it, the point is to use state as an intermediary for asynchronous values.