Skip to content

Async checks ​

A schema with checkAsync — e.g. "email is not taken" — works in useForm out of the box.

How it works ​

  • While typing, the check runs after a debounce pause (300 ms by default) — no request per keystroke.
  • While it runs, form.validating is true.
  • A stale response never overwrites a newer result: if the user changed the value meanwhile, the old response is ignored.
  • A field's async check runs only if its synchronous rules passed — an invalid email never reaches the server.
  • handleSubmit and validate check immediately, without the pause.

Example ​

vue
<script setup lang="ts">
const Signup = object({
  email: pipe(
    string(),
    email(),
    checkAsync(async (v) => !(await api.get('/email-exists', { params: { email: v } })).data, 'Email is taken'),
  ),
});

const form = useForm(Signup, { initial: { email: '' }, debounce: 500 });
</script>

<template>
  <input v-model="form.values.email" @blur="form.touch('email')" />
  <span v-if="form.validating">Checking…</span>
  <span v-else-if="form.errors.email">{{ form.errors.email }}</span>
</template>

See also ​