https://github.com/sergiodxa/use-mutation
🧬 Run side-effects safely in React
https://github.com/sergiodxa/use-mutation
hooks mutations react-query reactjs side-effects swr typescript use-mutation
Last synced: 11 months ago
JSON representation
🧬 Run side-effects safely in React
- Host: GitHub
- URL: https://github.com/sergiodxa/use-mutation
- Owner: sergiodxa
- License: mit
- Created: 2020-07-22T21:14:16.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-02-17T10:57:47.000Z (about 3 years ago)
- Last Synced: 2025-03-31T12:06:46.091Z (12 months ago)
- Topics: hooks, mutations, react-query, reactjs, side-effects, swr, typescript, use-mutation
- Language: TypeScript
- Homepage:
- Size: 1.28 MB
- Stars: 120
- Watchers: 2
- Forks: 8
- Open Issues: 13
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README

 
Specially useful to run requests against an API, and combined with [SWR](https://swr.vercel.app).
## Usage
Install it:
```sh
$ yarn add use-mutation
```
Import it:
```ts
import useMutation from 'use-mutation';
```
Create a function which runs a mutation
```tsx
async function createComment({
authorId,
comment,
}: {
authorId: number;
comment: string;
}) {
const res = await fetch('/api/comments', {
method: 'POST',
body: JSON.stringify({ authorId, comment }),
});
if (!res.ok) throw new Error(res.statusText);
return await res.json();
}
```
Use your function with `useMutation`
```tsx
function CommentForm({ authorId }) {
const [comment, setComment] = React.useState('');
const [mutate, { status }] = useMutation(createComment, {
onMutate({ input }) {
// do something before the mutation run
return () => {
// rollback changes if the mutation failed
};
},
onSuccess({ data, input }) {
// do something once the mutation succeeded
},
onFailure({ error, rollback, input }) {
// do something once the mutation failed
},
onSettled({ status, error, data, rollback, input }) {
switch (status) {
case 'success': {
// do something if the mutation succeeded
}
case 'failure': {
// do something if the mutation failed
}
}
},
});
const handleSubmit = React.useCallback(
function handleSubmit(event) {
mutate({ authorId, comment });
},
[mutate, comment]
);
// render your UI
}
```
### Usage with SWR
If you are using SWR, you can use `useMutation` to run your mutations to perform Optimistic UI changes.
```tsx
import { cache, mutate } from 'swr';
function createComment(input) {
// ...
}
function useCreateComment() {
return useMutation(createComment, {
onMutate({ input }) {
const oldData = cache.get('comment-list');
// optimistically update the data before your mutation is run
mutate('comment-list', current => current.concat(input), false);
return () => mutate('comment-list', oldData, false); // rollback if it failed
},
onFailure({ rollback }) {
if (rollback) rollback();
},
});
}
```
This way when you run `mutate`, it will first optimistically update your SWR cache and if it fails it will rollback to the old data.
## API Reference
```tsx
const [mutate, { status, data, error, reset }] = useMutation<
Input,
Data,
Error
>(mutationFn, {
onMutate,
onSuccess,
onFailure,
onSettled,
throwOnFailure,
useErrorBoundary,
});
const promise = mutate(input, {
onSuccess,
onSettled,
onError,
throwOnFailure,
});
```
### Hook Generic
> Only if you are using TypeScript
- `Input = any`
- The data your mutation function needs to run
- `Data = any`
- The data the hook will return as result of your mutation
- `Error = any`
- The error the hook will return as a failure in your mutation
### Hook Options
- `mutationFn(input: Input): Promise`
- **Required**
- A function to be executed before the mutation runs.
- It receives the same input as the mutate function.
- It can be an async or sync function, in both cases if it returns a function it will keep it as a way to rollback the changed applied inside onMutate.
- `onMutate?({ input: Input }): Promise | rollbackFn | undefined`
- Optional
- A function to be executed before the mutation runs.
- It receives the same input as the mutate function.
- It can be an async or sync function, in both cases if it returns a function.
- it will keep it as a way to rollback the changed applied inside `onMutate`
- `onSuccess?({ data: Data, input: Input }): Promise | void`
- Optional
- A function to be executed after the mutation resolves successfully.
- It receives the result of the mutation.
- If a Promise is returned, it will be awaited before proceeding.
- `onFailure?({ error: Error, rollback: rollbackFn, input: Input }): Promise | void`
- Optional
- A function to be executed after the mutation failed to execute.
- If a Promise is returned, it will be awaited before proceeding.
- `onSettled?({ status: 'success' | 'failure', error?: Error, data?: Data, rollback?: rollbackFn, input: Input}): Promise | void`
- Optional
- A function to be executed after the mutation has resolves, either successfully or as failure.
- This function receives the error or the result of the mutation.
- If a Promise is returned, it will be awaited before proceeding.
- `throwOnFailure?: boolean`
- Optional
- If defined as `true`, a failure in the mutation will cause the `mutate` function to throw. Disabled by default.
- `useErrorBoundary?: boolean` (default false)
- Optional
- If defined as `true`, a failure in the mutation will cause the Hook to throw in render time, making error boundaries catch the error.
### Hook Returned Value
- `mutate(input: Input, config: Omit, 'onMutate' | 'useErrorBoundary'> = {}): Promise`
- The function you call to trigger your mutation, passing the input your mutation function needs.
- All the lifecycle callback defined here will run _after_ the callback defined in the Hook.
- `status: 'idle' | 'running' | 'success' | 'failure'`
- The current status of the mutation, it will be:
- `idle` initial status of the hook, and the status after a reset
- `running` if the mutation is currently running
- `success` if the mutation resolved successfully
- `failure` if the mutation failed to resolve
- `data: Data`
- The data returned as the result of the mutation.
- `error: Error`
- The error returned as the result of the mutation.
- `reset(): void
- A function to reset the internal state of the Hook to the orignal idle and clear any data or error.
## Author
- [Sergio XalambrÃ](https://sergiodxa.com) - [Able](https://able.co)
## License
The MIT License.