useMutation
A mutation allows you to call a Moopsy method as a side-effect. In other words, as opposed to a query where the Moopsy Server is called immediately as soon as useQuery
is run, useMutation
returns a handle which you can use to call the method.
Usage
import { moopsyClient } from './your-moopsy-client';
import * as FooBP from '../blueprints/foo.ts';
const fooMutation = moopsyClient.useMutation<FooBP.Plug>(FooBP, options);
const onClick = React.useCallback(() => {
fooMutation.call({ bar: "baz" }).then((res) => {
// res is the result of fooMutation (if any)
}).catch((err: MoopsyError) => {
// Moopsy enforces that err will always be a MoopsyError
});
}, []);
Usage with Query Side Effects
You can pass in a UseMoopsyQueryRetVal
(value returned from calling moopsyClient.useQuery()
) and whenever the mutation is called, the Moopsy Server will subsequently process a call to the query method and return both the mutation result and the new query values in a single trip and the query(s) you passed in to the mutation will be updated with the new data.
const countQuery = moopsyClient.useQuery<GetCountBP.Plug>(GetCountBP, 'some-param');
const incMutation = moopsyClient.useQuery<IncCountBP.Plug>(IncCountBP, { querySideEffects: [countQuery] });
const onClick = React.useCallback(() => {
incMutation.call({ incBy: 1 }).then((res) => {
// res is the result of the incMutation (if any), and countQuery.data has been re-run and updated with the new data
});
}, []);
The querySideEffects
array is allowed to contain null
, so you can safely pass in null instead of a side effect in situations where the presence of a query is optional.
Update UI based on mutation status
In the below example, we use the reactive isLoading
and error
values from UseMoopsyMutationRetVal
to update the UI based on the status of the mutation call.
const fooMutation = moopsyClient.useQuery<FooBP.Plug>(FooBP);
const onClick = React.useCallback(() => {
// Since we handle the error state in the UI, we don't add a catch()
// which means we need to void the mutation (prevents uncaught rejection)
// errors from bubbling up
void fooMutation.call({ some: "data" }).then((res) => {
// ...
});
}, []);
return (
<div>
{fooMutation.isLoading ?
<button disabled>Loading...</button>
:
<button onClick={onClick}>Submit</button>
}
{fooMutation.error !== false ?
<div style={{color:"red"}}>{fooMutation.error.description}</div>
: null}
</div>
)