memoize
The
memoize
function is part of Conform's future export. These APIs are experimental and may change in minor versions. Learn more
A utility function that memoizes function calls, caching only the most recent result to prevent redundant async validations in forms.
import { memoize } from '@conform-to/zod/v3/future'; // Or import '@conform-to/zod/v4/future'
const memoizedFn = memoize(fn, isEqual);
#Parameters
fn: T
The function to memoize. Can be synchronous or asynchronous.
isEqual?: (prevArgs: Parameters<T>, nextArgs: Parameters<T>) => boolean
Optional custom equality function to compare arguments. Defaults to shallow comparison using Object.is()
.
const memoizedFn = memoize(
async (user: { id: string; name: string }) => {
return await validateUser(user);
},
// Custom equality - only compare by ID
(prevArgs, nextArgs) => prevArgs[0].id === nextArgs[0].id,
);
#Returns
A memoized function with the same signature as the original function, plus:
clearCache(): void
Method to manually clear the memoization cache.
#Example
import { memoize } from '@conform-to/zod/v3/future'; // Or import '@conform-to/zod/v4/future'
import { useMemo } from 'react';
function Example() {
const validateUsername = useMemo(
() =>
memoize(async function isUsernameUnique(username: string) {
const response = await fetch(`/api/users/${username}`);
if (!response.ok) {
return ['Username is already taken'];
}
return null;
}),
[],
);
const { form, fields } = useForm({
// A standard schema for basic validations
schema,
async onValidate({ value, error }) {
// Validate username uniqueness only if username is provided and has no other errors
if (value.username && !error.fieldErrors.username) {
const messages = await validateUsername(value.username);
if (messages) {
error.fieldErrors.username = messages;
}
}
},
});
// ...
}
#Tips
Schema-level validation
memoize
can also be used directly in schema libraries with async validation support, such as Zod:
const schema = z.object({
username: z.string().refine(memoize(isUsernameUnique), {
message: 'Username is already taken',
}),
});
Memoize at the component level
Always wrap memoized functions in useMemo
to prevent recreating them on each render:
const validateUsername = useMemo(() => memoize(isUsernameUnique), []);
Avoid defining memoized functions in the global scope, as this can lead to shared state across multiple component instances.