You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在普通业务函数中正确调用Apollo Client的useMutation Hook?

解决方案

核心问题本质

你违反了React Hook的调用规则:Hook只能在函数组件或者自定义Hook的顶层作用域调用,不能在普通业务函数、异步回调内部调用。你原先的createNotification是普通函数,内部调用了useMutation这个Hook,在addMovie的异步回调中执行时自然会触发报错。

代码修改步骤

第一步:改造通知创建逻辑为自定义Hook

将CreateNotification.tsx中的普通函数改为符合React规范的自定义Hook,不要直接执行mutation,而是返回触发mutation的可调用函数:

// CreateNotification.tsx
import { useMutation } from '@apollo/client';
import resolvers from '../resolvers';

// 自定义Hook命名必须以use开头
const useCreateNotification = () => {
  // 在Hook顶层调用useMutation,拿到触发函数
  const [triggerCreate] = useMutation(resolvers.mutations.CreateNotification);

  // 返回实际执行业务逻辑的函数,供外部按需调用
  return (notification: { movie: IMovie, user: any }) => {
    triggerCreate({
      variables: {
        movie_id: notification.movie.id,
        actor_id: notification.user.id,
        message: `${notification.user.user_name} 已将 ${notification.movie.original_title} 添加到观影列表`,
      },
    });
  };
};

export default useCreateNotification;

第二步:调整组件内调用逻辑

在AddMovie.tsx组件顶层调用自定义Hook拿到触发函数,再在异步请求完成的回调中调用该函数即可:

// AddMovie.tsx
import useCreateNotification from './CreateNotification';

const AddMovieToWatchList = ({movie}: {movie: IMovie}) => {
  // 组件顶层调用自定义Hook,拿到通知触发函数
  const createNotification = useCreateNotification();
  const [addUserToMovie] = useMutation(resolvers.mutations.AddUserToMovie);

  const addMovie = async (movie: IMovie) => {
    await addUserToMovie({
      variables: {...movie, tmdb_id: movie.id},
      update: (cache, {data}) => {
        cache.modify({
          fields: {
            moviesFromUser: () => {
              return [...data.addUserToMovie];
            },
          },
        });
      },
    }).then(() => {
      // 异步请求完成后按需调用通知触发逻辑
      createNotification({movie: movie, user: currentUserVar()});
    });
  };

  return (
    <a className={classes.addMovie} onClick={() => addMovie(movie)}>
      添加电影到我的观影列表
    </a>
  );
}

实现原理

自定义Hook内部的useMutation是在组件渲染的顶层阶段执行的,完全符合React Hook的调用规则。返回的触发函数只是普通的业务执行函数,可以在任意时机(比如异步回调、点击事件回调)调用,不会触发Hook规则报错,同时也不会在组件渲染时自动执行,只有你主动调用时才会发起创建通知的请求。


内容的提问来源于stack exchange,提问作者Peter Boomsma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 07:36:02