Search code examples
typescriptasync-awaiteslintprimereact

TypeScript PrimeReact async Button onClick handler ESLint error


I try to export data from DataTable in PrimeReact. The Button onClick doesn't allow async callback as eslint told. How can I call this function properly?

    const exportCSV = useCallback(async (_selectionOnly: boolean) => {
        //dt.current.exportCSV({ selectionOnly });
        try {
            const result = await fetch("/api/admin/crud/channels");
            const data: ChannelValue[] = await result.json() as ChannelValue[];
            const csv = convertToCSV(data);
            downloadCsvFile(csv, "download.csv");
        } catch (e: unknown) {
            show(toast, "error", "Please check is the powermeter-api runing.");
        }
    }, []);

    const header = (
        <>
            <div className="grid cols-2 justify-content-end w-ull">
                <div className="flex justify-content-end w-6 ">
                    <h2>Channels</h2>
                </div>
                <div className="flex align-items-center justify-content-end gap-2 end w-6 ">
                    <Button
                        type="button"
                        icon="pi pi-file"
                        rounded
// problem ===>         onClick={() => exportCSV(false)}
                        data-pr-tooltip="CSV"
                    />
                </div>
            </div>
        </>
    );

ESLint error: "Promise-returning function provided to attribute where a void return was expected.eslint@typescript-eslint/no-misused-promises"

Please help me find right way to this.


Solution

  • "Promise-returning function provided to attribute where a void return was expected.eslint@typescript-eslint/no-misused-promises"

    This error is happening because onClick expects a function that returns void, but your function returns Promise<void>. That's fine as far as typescript is concerned, but the no-misused-promises lint rule is stricter. You can fix the code by explicitly setting the return type to void:

    onClick={(): void => exportCSV(false)}
    

    Or:

    const exportCSV = useCallback(async (_selectionOnly: boolean): void => {
      // ...
    }, []);
    

    Alternatively, if you feel this lint rule is too strict, you can disable it. To disable just this part of no-misused-promises, add this to your .eslintrc file:

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

    To disable all parts of the rule:

    "@typescript-eslint/no-misused-promises": "off"
    

    Documentation for this rule