停止重新渲染组件的 useMutation 并忽略结果

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

我有一个这样调用的突变(这不是实际的突变调用,而是一个最小的例子):

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>
    </>
  );
};

每当调用 onClick 时,都会重新渲染整个组件。这不是我想要的,因为我不关心突变的结果。有什么方法可以阻止 myMutation 导致重新渲染,并完全忽略结果吗?

这可能是因为变异是 return 规范化对象,该组件或更高组件通过像 useQuery 这样的钩子依赖该对象。

如果您不关心突变的结果,请确保它不是 return 规范化对象。

类似

mutation SomeMutation ($input: SomeMutationInput!){
  someMutation (input: $input){
    ok
  }
}

useMutation 是一个钩子,其中有 state 导致重新渲染

请参阅下面的 useMultation 类型:

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

loading 状态是导致重新渲染的状态,因此您在哪个组件中删除 useMutation 它会因此重新渲染 state


一个可能的修复方法是将带有 useMutation 的组件与另一个

分开

像这样:

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

检查现场示例:

嗯,如果你不需要突变返回的data,你也可以传递ignoreResults选项。数据不会从变异挂钩返回,但 loading 两者都不会调用,这会阻止重新渲染。

https://www.apollographql.com/docs/react/data/mutations/#ignoreresults

const [someMutation] = useSomeMutation({
 ignoreResults: true,
});

以下应该有效(未测试)

  • 由于您不想重新渲染,因此不需要使用具有状态的 useMutation 挂钩。
  • 相反,您可以直接导入 apollo-client 并在其上使用 mutate,而无需使用 useMutation 挂钩。
  • 您可以选择在 .then 函数中使用结果或删除它。
import { apolloClient } from '../yourApolloClientFile';


const App = () => {

  const myMutation = (vars) => apolloClient.mutate({
    mutation: gql`
        mutation Test($updateUserId: ID!, $updateUserInput: UpdateUserInput!) {
          updateUser(id: $updateUserId, input: $updateUserInput) {
            id
            firstname
            age
          }
        }
      `,
    variables: vars
  })
    .then(result => console.log(result))
    .catch(error => console.log(error))


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

  // Called when the button is clicked
  const update = () => {
    myMutation({
      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>
    </>
  );
};