Search code examples
reactjsapolloapollo-client

Stop `useMutation` from re-rendering component and ignore result


I have a mutation called like this (this isn't the actual mutation call, but a minimal example):

const App = () => {
  const [myMutation] = useMutation(gql`
    mutation Test($updateUserId: ID!, $updateUserInput: UpdateUserInput!) {
      updateUser(id: $updateUserId, input: $updateUserInput) {
        id
        firstname
        age
      }
    }
  `);

  // Runs every time this component is rendered
  console.log("rendered");

  // Called when the button is clicked
  const update = () => {
    myMutation({
      variables: {
        updateUserId: 1,
        updateUserInput: {
          age: Math.round(Math.random() * 10 + 5) // Set a random age from 5 - 15
        }
      }
    });
  };

  return (
    <>
      <h1>Update Test</h1>
      <button onClick={update}>Update!</button>
    </>
  );
};

Whenever onClick is called, the whole component is re-rendered. This is not what I want, as I don't care about the result of the mutation. Is there any way to stop myMutation from causing a re-render, and ignore the result completely?


Solution

  • useMutation is a hook and it has state in it which cause a re-render

    See the useMultation type bellow:

    export interface MutationResult<TData = any> {
        data?: TData | null;
        error?: ApolloError;
        loading: boolean;
        called: boolean;
        client: ApolloClient<object>;
    }
    

    The loading state is the one causing re-render, so in which component you delcare useMutation it will re-render due to that state


    One possible fix is to separate the component with useMutation to another one

    Something like this:

    function App() {
      return (
        <>
          <Header />  // <-- this coponent won't re-render
          <UpdateUserButton />  // <-- useMutation is in here!
        </>
      );
    }
    

    Checkout the live example:

    Edit sweet-cohen-4w6ef