Async function passed as prop into React component causing @typescript-eslint/no-misused-promises error

4.5k Views Asked by At

I have the following asynchronous submitNewPatient function which is throwing @typescript-eslint/no-misused-promises error message from elint. Is it possible to adjust the function such that it removes this error?

const submitNewPatient = async (values: PatientFormValues) => {
    try {
      const { data: newPatient } = await axios.post<Patient>(
        `${apiBaseUrl}/patients`,
        values
      );
      dispatch({ type: "ADD_PATIENT", payload: newPatient });
      closeModal();
    } catch (e: unknown) {
      if (axios.isAxiosError(e)) {
        console.error(e?.response?.data || "Unrecognized axios error");
        setError(
          String(e?.response?.data?.error) || "Unrecognized axios error"
        );
      } else {
        console.error("Unknown error", e);
        setError("Unknown error");
      }
    }
  };

Component used to pass function as a prop:

<AddPatientModal
        modalOpen={modalOpen}
        onSubmit={submitNewPatient}
        error={error}
        onClose={closeModal}
      />

I have also tried the following which removes the eslint error message based. However, seems like I am not entering the async code block (perhaps not triggering the async() function):

  const submitNewPatient = (values: PatientFormValues) => {
    async () => {
      try {
        const { data: newPatient } = await axios.post<Patient>(
          `${apiBaseUrl}/patients`,
          values
        );
        dispatch({ type: "ADD_PATIENT", payload: newPatient });
        closeModal();
      } catch (e: unknown) {
        if (axios.isAxiosError(e)) {
          console.error(e?.response?.data || "Unrecognized axios error");
          setError(
            String(e?.response?.data?.error) || "Unrecognized axios error"
          );
        } else {
          console.error("Unknown error", e);
          setError("Unknown error");
        }
      }
    };
  };
2

There are 2 best solutions below

1
On BEST ANSWER

I think the problem is with the async code block syntax. You need it to make it an IIFE (Immediately-invoked Function Expression for it to be executed immediately.

(async () => {
    await someAsyncFunction();
})();

Your submitNewPatient becomes -

const submitNewPatient = (values: PatientFormValues) => {
    (async () => {
      try {
        const { data: newPatient } = await axios.post<Patient>(
          `${apiBaseUrl}/patients`,
          values
        );
        dispatch({ type: "ADD_PATIENT", payload: newPatient });
        closeModal();
      } catch (e: unknown) {
        if (axios.isAxiosError(e)) {
          console.error(e?.response?.data || "Unrecognized axios error");
          setError(
            String(e?.response?.data?.error) || "Unrecognized axios error"
          );
        } else {
          console.error("Unknown error", e);
          setError("Unknown error");
        }
      }
    })();
  };
1
On

The problem is not in your code but in the ESLint rule or the ESLint config. React 17 and later can handle async functions as event handlers.

The IIFE gets rid of the ESLint error but the error should not appear in the first place. Unless you are using React 16 or earlier.

There was a lengthy discussion about the rule on Github.

The proposed solution is to remove the check for attributes or arguments:

{
  "@typescript-eslint/no-misused-promises": [
    "error",
    {"checksVoidReturn": {"attributes": false}}
  ]
}

https://typescript-eslint.io/rules/no-misused-promises/