All Projects → sergiodxa → use-mutation

sergiodxa / use-mutation

Licence: MIT License
🧬 Run side-effects safely in React

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to use-mutation

Swr
React Hooks for data fetching
Stars: ✭ 20,348 (+25020.99%)
Mutual labels:  hooks, swr
expansion-pack
🔋 Useful stack expansion for ts-nextjs-tailwind-starter
Stars: ✭ 16 (-80.25%)
Mutual labels:  swr, react-query
pinipig
🚀 Performant webservice framework
Stars: ✭ 25 (-69.14%)
Mutual labels:  hooks
tmdb-viewer
A movie browsing/favoriting app
Stars: ✭ 63 (-22.22%)
Mutual labels:  react-query
netease-music-app
网易云音乐移动端【React/Next/Vue】【Ant Design/Material UI】
Stars: ✭ 95 (+17.28%)
Mutual labels:  swr
swr-devtools
Devtools for SWR
Stars: ✭ 17 (-79.01%)
Mutual labels:  swr
hook-into-props
Tiny HoC to use React hooks with class components.
Stars: ✭ 44 (-45.68%)
Mutual labels:  hooks
react-usemiddleware
React >=16.7 hook, allowing to use standard Redux middleware with useReducer
Stars: ✭ 19 (-76.54%)
Mutual labels:  hooks
k-ramel
State manager for your components apps, the safe and easy way
Stars: ✭ 20 (-75.31%)
Mutual labels:  side-effects
react-stateful-component
Functional stateful React components with sideEffect support
Stars: ✭ 19 (-76.54%)
Mutual labels:  side-effects
static-template-nextjs
A Next.js based template of a blog built using the Collected Notes API
Stars: ✭ 19 (-76.54%)
Mutual labels:  swr
hulks
Olist custom linting hooks 💚 👽
Stars: ✭ 25 (-69.14%)
Mutual labels:  hooks
atomic-state
A decentralized state management library for React
Stars: ✭ 54 (-33.33%)
Mutual labels:  hooks
ieaseMusic
网易云音乐第三方🎵
Stars: ✭ 62 (-23.46%)
Mutual labels:  hooks
zoov
Use 🐻 Zustand with Module-like api
Stars: ✭ 24 (-70.37%)
Mutual labels:  hooks
gatsby-react-hooks
An example of using Gatsby with React hooks
Stars: ✭ 26 (-67.9%)
Mutual labels:  hooks
jitm
JITM is an automated tool to bypass the JIT Hooking protection on a .NET sample.
Stars: ✭ 27 (-66.67%)
Mutual labels:  hooks
ph-malhide
Process Hacker 2 hiding from external applications
Stars: ✭ 17 (-79.01%)
Mutual labels:  hooks
zhooks
Display Zsh hook functions and arrays
Stars: ✭ 36 (-55.56%)
Mutual labels:  hooks
bow-lite
🏹 Bow Lite is a cross-platform library for Typed Functional Programming in Swift
Stars: ✭ 27 (-66.67%)
Mutual labels:  side-effects

🧬 useMutation - Run side-effects safely in React

CI Publish

Specially useful to run requests against an API, and combined with SWR.

Usage

Install it:

$ yarn add use-mutation

Import it:

import useMutation from 'use-mutation';

Create a function which runs a mutation

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

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.

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({ status, rollback }) {
      if (status === 'failure' && 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

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<Data>
    • 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> | 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> | 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> | 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> | 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<Options<Input, Data, Error>, 'onMutate' | 'useErrorBoundary'> = {}): Promise<Data | undefined>
    • 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

License

The MIT License.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].