useSubmit
This hook is built on useLoad with a trimmed feature set: it supports only a few options and never runs automatically. It is typically used for network requests such as create, update, and delete.
Compared to useLoad, these capabilities are intentionally unavailable:
- No automatic loading —
submitis the only trigger; nothing runs on mount. - No request sharing —
keyis unavailable; every submission is independent. - No caching —
cacheKey/staleTimeare unavailable;submitalways sends the request. - No polling or auto-reload — the
polling*andautoReload*options are unavailable. - No
initialDataordefaultParams.
The returned submit is implemented by useLoad's force, so each submission cancels the previous pending submission and always sends the request.
How it works
submit(...params) forwards the params to the callback and returns a promise that resolves with the success data or rejects with the error. On failure, the same retry/fallback pipeline as useLoad applies — see Failure handling.
API
type LoadCallback = (...args: any[]) => Promise<any>;
interface UseSubmitOptions<Callback extends LoadCallback> {
idle?: boolean | IdleRequestOptions;
fallback?: Callback;
retry?: boolean | ((error: any) => boolean);
retryLimit?: number;
retryInterval?: number | ((count: number) => number);
fallbackRetry?: boolean | ((error: any) => boolean);
fallbackRetryLimit?: number;
fallbackRetryInterval?: number | ((count: number) => number);
onSuccess?: (data: Awaited<ReturnType<Callback>>) => void;
onFailure?: (error: any) => void;
onFinally?: () => void;
}
function useSubmit<Callback extends LoadCallback>(
callback: Callback,
options?: UseSubmitOptions<Callback>,
): {
submitting: boolean;
error: any;
submit: (...params: Parameters<Callback>) => ReturnType<Callback>;
};
Parameters:
callback: The submit function; its params are forwarded bysubmit. It must return a promise; the resolved value is the success data.options: Options object. All options are shared withuseLoadand behave identically — the summaries below are kept short; seeuseLoad's options for the full semantics.options.idle: Run the callback during the browser's idle periods. You can pass anIdleRequestOptionsobject to limit the max waiting time.options.fallback: An alternate source called after the retries ofcallbackare exhausted.options.retry: Enable retrying the callback. Default isfalse. It can be a function that receives the error and returns whether to retry.options.retryLimit: Callback retry limit. Default is3.options.retryInterval: Callback retry interval, in milliseconds. Defaults to exponential growth: thecount-th retry waits 2^(count-1) × 1000 ms. It can also be a function computing the wait from the retry number.options.fallbackRetry: Enable retrying the fallback function after it fails too. Default isfalse. It can be a function that receives the error and returns whether to retry.options.fallbackRetryLimit: Fallback retry limit. Default is3.options.fallbackRetryInterval: Fallback retry interval, in milliseconds. Defaults to exponential growth likeretryInterval. It can also be a function.options.onSuccess: Called on submit success with the data.options.onFailure: Called on submit failure with the error object.options.onFinally: Called when the submit settles (success or failure).
Results:
submitting: Submitting state. Initial value isfalse.error: The error of the most recent failure,nullon success.submit: Submit function. Its params are passed to thecallbackas is. Each submission cancels the previous pending submission and always sends the request.
Notes
- The pending submission is cancelled when the component unmounts; its returned promise then never settles.
Example
Refresh a list after submit — the typical create/update/delete workflow. onSuccess receives the result and calls update (local) and reload on the list's useLoad.
Click Submit — the number updates to the submitted result, then reloads.
import { useLoad, useSubmit } from "@lilib/hooks";
const fetchNumber = () => {
return new Promise<number>((resolve) => {
setTimeout(() => {
resolve(Math.random());
}, 1000);
});
};
const submitNumber = () => {
return new Promise<number>((resolve) => {
setTimeout(() => {
resolve(Math.random());
}, 1000);
});
};
function Example() {
const { data, loading, update, reload } = useLoad(fetchNumber);
const { submit, submitting, error } = useSubmit(submitNumber, {
onSuccess: (result) => {
update(result);
reload();
},
});
return (
<div>
<button onClick={() => submit()}>{submitting ? "Submitting" : "Submit"}</button>
{error && <div>Error: {error.message}</div>}
Number: {data} {loading ? "(Loading...)" : ""}
</div>
);
}
export default Example;