Skip to main content

useSubmit


Introduction

This hook is created to mutate data on the server or to make requests in a controlled manner. It uses the Submit Dispatcher to handle requests and the Cache to manage the overall state of the data.

The minimum requirement to use useSubmit is to have a prepared Command.

If you intend to retrieve data from the server, we recommend useFetch hook.


Initialization

const { submit, submitting, onSubmitSuccess, onSubmitError, onSubmitFinished } = useSubmit(postLogin);

How it works?

useSubmit executes the command when a submit() function returned from it gets triggered. It uses dependency tracking to limit re-rendering and help with the performance. Under the hood the communication with the core systems is established by the events emitters. There are many helpful "helper hooks" that get returned from the hook like onSubmitSuccess, onSubmitError, onSubmitFinished and many more to help you handle interesting events in the request flow and lifecycle. We used this approach to not overload the base hook with the callbacks logic which cause low readability of the code and increase complication level. Thanks to this we can easily organize our code.

import { useSubmit } from "@better-typed/react-hyper-fetch";
import { postLogin } from "server";

interface Values {
email: string;
password: string;
}

const LoginPage: React.FC = () => {
const { submit, submitting, onSubmitSuccess, onSubmitError, onSubmitFinished } = useSubmit(postLogin);

onSubmitSuccess(({ response }) => {
console.log(response); // { token: string, refreshToken: string }
});

onSubmitError(({ response }) => {
console.log(response); // { message: string }
});

onSubmitFinished(({ response }) => {
const [payload, error, status] = response;
console.log(payload); // { token: string, refreshToken: string } | null
console.log(error); // { message: string } | null
console.log(status); // 200 / 400 / 404 / 500 ...
});

const onSubmit = (values: Values) => {
submit({ data: values });
};

return (
<Formik initialValues={initialValues} onSubmit={onSubmit} validationSchema={validationSchema}>
<Form>
{error && <Alert severity="error">{error.error_message}</Alert>}
<FormInput name="email" label="Email" placeholder="Fill your email" />
<FormInput type="password" name="password" label="Password" placeholder="Fill your password" />
<Button type="submit" variant="contained" disabled={submitting} className={styles.submit}>
Log in
</Button>
</Form>
</Formik>
);
};

Passing data and params

Passing of the data or parameters can take place in several ways. One of them is to use methods on the Command such as setData or setParams.

const { submit } = useSubmit(patchUser.setParams({ userId: 1 }).setData({ name: "New Name" }));

However, we often encounter the need to pass parameters dynamically, in this case we can do it right in the submit function options.

const { submit } = useSubmit(patchUser);

const handleSubmit = (id: number, name: string) => {
submit({ data: { name }, params: { userId: id }, queryParams: { search: "test" } });
};

Options

Configuration options for this hook provided as a second parameter.

const { ... } = useSubmit(command, options)

Name Type Description
bounce boolean Enable/disable debouncing for often changing keys or refreshing, to limit requests to server.
bounceTime number How long it should bounce requests.
bounceType "debounce" | "throttle" Possibility to choose between debounce and throttle approaches
deepCompare boolean | query Deep comparison function for hook to check for equality in incoming data, to limit rerenders.
dependencyTracking boolean If `true` it will rerender only when values used by our component gets changed. Otherwise it will rerender on any change.
disabled boolean Disable fetching
initialData CacheValueType["data"] | null If cache is empty we can use placeholder data.


Returns

Returned values from this hook.

const values = useSubmit(command);

Name Type Description
setData (data: ExtractResponse<T>, emitToCache: boolean) => void Action to set custom data. We can do it locally(inside hook state) or in cache(all related sources) with 'emitToCache' option.
setError (error: ExtractError<T>, emitToCache: boolean) => void Action to set custom error. We can do it locally(inside hook state) or in all hooks with 'emitToCache' option.
setLoading (loading: boolean, emitToHooks: boolean) => void Action to set custom loading. We can do it locally(inside hook state) or in cache(all related sources) with 'emitToCache' option
setRetries (retries: number, emitToCache: boolean) => void Action to set custom retries count. We can do it locally(inside hook state) or in cache(all related sources) with 'emitToCache' option
setStatus (status: number, emitToCache: boolean) => void Action to set custom status. We can do it locally(inside hook state) or in cache(all related sources) with 'emitToCache' option
setTimestamp (timestamp: Date, emitToCache: boolean) => void Action to set custom timestamp. We can do it locally(inside hook state) or in cache(all related sources) with 'emitToCache' option
bounce {'{'} active: boolean, reset: () => void {'}'} Data related to current state of the bounce usage
submitting boolean Request loading state
abort () => void Callback which allows to cancel ongoing requests from given queueKey.
onSubmitAbort (callback: OnErrorCallbackType<T>) => void Helper hook listening on aborting of requests. Abort events are not triggering onError callbacks.
onSubmitDownloadProgress (callback: OnProgressCallbackType) => void Helper hook listening on download progress ETA. We can later match given requests by their id's or command instance which holds all data which is being transferred.
onSubmitError (callback: OnErrorCallbackType<T>) => void Helper hook listening on error response.
onSubmitFinished (callback: OnFinishedCallbackType<T>) => void Helper hook listening on any response.
onSubmitOfflineError (callback: OnErrorCallbackType<T>) => void Helper hook listening on request going into offline awaiting for network connection to be restored. It will not trigger onError when 'offline' mode is set on command.
onSubmitRequestStart (callback: OnStartCallbackType<T>) => void Helper hook listening on request start.
onSubmitResponseStart (callback: OnStartCallbackType<T>) => void Helper hook listening on response start(before we receive all data from server).
onSubmitSuccess (callback: OnSuccessCallbackType<T>) => void Helper hook listening on success response.
onSubmitUploadProgress (callback: OnProgressCallbackType) => void Helper hook listening on upload progress ETA. We can later match given requests by their id's or command instance which holds all data which is being transferred.
revalidate (invalidateKey: string | RegExp | CommandInstance) => void Revalidate current command resource or pass custom key to trigger it by invalidationKey(Regex / cacheKey).
submit (parameters: Parameters<T["send"]>) => Promise<ExtractClientReturnType<T>> Method responsible for triggering requests. It return Promise which will be resolved with the request.