Async event handlers

First off, I come from Vue. I've barely touched React before, but not much. This is my first time using t3, so my assumptions could be wildly wrong here. How are you supposed to do async operations in reaction to dom events? If I create an async handler function, and attaches it to an input's change event (onChange={handleChange}), ESLint fires off with ESLint: Promise-returning function provided to attribute where a void return was expected.(@typescript-eslint/no-misused-promises). If I change it to onChange={(event) => {handleChange(event)}}, it hits me with ESLint: Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler or be explicitly marked as ignored with the void operator.(@typescript-eslint/no-floating-promises). When I then add void, onChange={(event) => {void handleChange(event)}}, there is no more complaining. Is this how you're supposed to do it? Am I supposed to not have async event handlers?
6 Replies
aryan1306
aryan1306•10mo ago
GitHub
[no-misused-promises] async react callback properties when void exp...
I have tried restarting my IDE and the issue persists. I have updated to the latest version of the packages. I have read the FAQ and my problem is not listed. Repro { "rules": { "no-...
Josh
Josh•10mo ago
Can you give a full example of where your getting an error? I have a feeling your not quite something the "react way"
Cathrine
Cathrine•10mo ago
This showed me that you can disable the check for void promises
Cathrine
Cathrine•10mo ago
TS Playground - An online editor for exploring TypeScript and JavaS...
The Playground lets you write TypeScript or JavaScript online in a safe and sharable way.
Josh
Josh•10mo ago
this actually looks fine tbh. One thing i would recomend to make the types easier on yourself is changing it to this
import { api } from "~/utils/api";

import React from 'react'

export default function FileUpload() {
const uploadTextFileMutation = api.file.uploadTextFile.useMutation();

const handleUploadFile = async (file: File) => {

if (file.type !== "text/plain") {
return;
}

uploadTextFileMutation.mutate(await file.text());
};

return (
<input
onChange={(e) => {
const file = e.target.files?.item(0)
file && handleUploadFile(file);
}}
type="file"
accept="text/plain"
/>
)
}
import { api } from "~/utils/api";

import React from 'react'

export default function FileUpload() {
const uploadTextFileMutation = api.file.uploadTextFile.useMutation();

const handleUploadFile = async (file: File) => {

if (file.type !== "text/plain") {
return;
}

uploadTextFileMutation.mutate(await file.text());
};

return (
<input
onChange={(e) => {
const file = e.target.files?.item(0)
file && handleUploadFile(file);
}}
type="file"
accept="text/plain"
/>
)
}
Mocha
Mocha•10mo ago
Another way:
import { api } from '~/utils/api'

export default function FileUpload() {
const { mutate: uploadTextFile } = api.file.uploadTextFile.useMutation()

async function handleUploadFile(file: File) {
if (file.type !== 'text/plain') return
const text = await file.text().catch(() => undefined)
if (!text?.length) return

uploadTextFile(text)
}

return (
<input
type='file'
accept='text/plain'
onChange={event => {
const file = event.currentTarget.files?.item(0)
if (!file) return
void handleUploadFile(file)
}}
/>
)
}
import { api } from '~/utils/api'

export default function FileUpload() {
const { mutate: uploadTextFile } = api.file.uploadTextFile.useMutation()

async function handleUploadFile(file: File) {
if (file.type !== 'text/plain') return
const text = await file.text().catch(() => undefined)
if (!text?.length) return

uploadTextFile(text)
}

return (
<input
type='file'
accept='text/plain'
onChange={event => {
const file = event.currentTarget.files?.item(0)
if (!file) return
void handleUploadFile(file)
}}
/>
)
}