Redux Toolkit结合Apollo Client使用GraphQL Mutations无响应问题求助
问题分析与解决方案
你遇到的核心问题是在Redux Thunk中直接使用React Hook useMutation,这违反了React Hook的使用规则——Hooks只能在React组件或自定义Hook的顶层调用,Thunk是普通异步函数,无法正确执行Hook,导致请求根本没有发起。
错误原因拆解
useMutation是React Hook,必须在React组件/自定义Hook的渲染流程中调用,Thunk不属于这个上下文,所以调用后不会生成有效的mutation函数,login()自然不会触发网络请求。- 这种写法甚至可能在控制台抛出Hook规则违反的错误,只是你没注意到。
正确实现方式
不要在Thunk里用useMutation,直接使用Apollo Client实例调用mutate方法即可。
步骤1:确保Apollo Client实例可导入
先在项目中创建并导出Apollo Client实例(比如src/apolloClient.js):
import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client'; const httpLink = createHttpLink({ uri: '你的GraphQL服务器地址', // 替换成实际地址 }); export const client = new ApolloClient({ link: httpLink, cache: new InMemoryCache(), });
步骤2:修正Redux Thunk
导入Apollo Client实例,直接调用mutate发起请求:
import { createAsyncThunk } from "@reduxjs/toolkit"; import { client } from "../../apolloClient"; import { LOGIN_USER } from "../../graphql/mutations/auth"; export const Authenticate = createAsyncThunk( "auth/login", async (data, thunkAPI) => { const { email, password } = data; try { // 直接用Apollo Client实例发起mutation const response = await client.mutate({ mutation: LOGIN_USER, variables: { email, password }, }); // 返回登录成功的用户数据 return response.data.login; } catch (error) { // 提取并返回错误信息 const errorMsg = error.graphQLErrors?.[0]?.message || error.networkError?.message || '登录失败'; return thunkAPI.rejectWithValue(errorMsg); } } );
步骤3:组件代码保持不变
你之前的组件dispatch代码无需修改,现在调用dispatch(Authenticate({email, password}))就能正常发起网络请求了。
备选方案:在组件中使用useMutation并同步到Redux
如果你更习惯用Apollo的Hook,可以在组件中直接调用useMutation,然后在回调中把结果同步到Redux:
import { useMutation } from "@apollo/client"; import { Authenticate } from "../../features/user/userActions"; import { useDispatch } from "react-redux"; import { LOGIN_USER } from "../../graphql/mutations/auth"; const LoginComponent = () => { const dispatch = useDispatch(); const [email, setEmail] = useState(""); const [password, setPassword] = useState(""); // 在组件中使用useMutation const [login] = useMutation(LOGIN_USER, { onCompleted: (data) => { // 登录成功后同步到Redux dispatch(Authenticate.fulfilled(data.login)); }, onError: (error) => { // 错误时同步到Redux const errorMsg = error.graphQLErrors?.[0]?.message || '登录失败'; dispatch(Authenticate.rejected(errorMsg)); }, }); const handleSubmit = async (event) => { event.preventDefault(); // 直接调用mutation函数 await login({ variables: { email, password } }); }; return ( // 你的表单JSX ); };
内容的提问来源于stack exchange,提问作者Jarliev Pérez
相关产品推荐
相关产品推荐

