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

使用Apollo Link State无法添加Todo的问题求助

问题排查与解决方案

从你给出的报错信息和代码来看,你遇到的TypeError: Object(WEBPACK_IMPORTED_MODULE_0_graphql_tag["gql"]) is not a function是直接阻碍addTodo mutation工作的原因,再结合你手动配置Apollo Client的场景,我们可以从以下几个方向逐步解决:

1. 先解决graphql-tag导入的直接错误

这个报错的核心是你的代码里gql方法没有被正确导入,常见原因有两种:

  • 导入方式不匹配依赖版本:graphql-tag新版本中gql是默认导出,但旧版本为命名导出。你可以尝试修改导入语句:
    把当前的:
    import gql from "graphql-tag";
    
    改成命名导入:
    import { gql } from "graphql-tag";
    
  • 依赖版本不兼容:运行npm ls graphql-tag查看当前版本,确保它和apollo-client、react-apollo版本匹配。如果版本差异过大,建议重新安装兼容版本:
    npm install graphql-tag@latest react-apollo@latest apollo-client@latest
    

你的addTodo mutation使用了@client指令,属于本地状态操作。由于你手动配置Apollo Client而非使用Apollo Boost,必须正确设置clientState链接,否则本地mutation无法触发:

示例正确配置代码

import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';
import { withClientState } from 'apollo-link-state';
import { gql } from 'graphql-tag';

// 定义本地状态查询(用于读取todos)
const GET_TODOS = gql`
  query GetTodos {
    todos @client {
      id
      text
      completed
    }
  }
`;

// 本地mutation的resolvers,必须实现addTodo逻辑
const resolvers = {
  Mutation: {
    addTodo: (_, { text }, { cache }) => {
      // 读取现有todos
      const { todos } = cache.readQuery({ query: GET_TODOS });
      // 创建新todo
      const newTodo = {
        id: Date.now().toString(),
        text,
        completed: false,
        __typename: 'Todo',
      };
      // 写入缓存
      cache.writeQuery({
        query: GET_TODOS,
        data: { todos: [...todos, newTodo] },
      });
      return newTodo;
    },
  },
};

// 本地状态默认值
const defaults = {
  todos: [],
};

// 初始化缓存与链接
const cache = new InMemoryCache();
const stateLink = withClientState({ resolvers, defaults, cache });
const coinbaseLink = new HttpLink({ uri: '你的Coinbase API地址' });

// 创建Apollo Client,注意stateLink要放在链路最前面
const client = new ApolloClient({
  link: stateLink.concat(coinbaseLink),
  cache,
});

如果配置中缺少resolvers的addTodo实现,或者clientState链接未正确加入链路,即使解决了gql导入问题,addTodo也不会生效。

3. 优化TodoForm的错误捕获

给Mutation组件添加错误处理逻辑,能更直观地看到后续报错细节:

import React from "react";
import { gql } from "graphql-tag";
import { Mutation } from "react-apollo";

const ADD_TODO = gql`
  mutation addTodo($text: String!) {
    addTodo(text: $text) @client {
      id
    }
  }
`;

const TodoForm = () => (
  <Mutation mutation={ADD_TODO} onError={(err) => console.error("添加Todo失败:", err)}>
    {(addTodo, { loading, error }) => {
      if (error) return <p>错误:{error.message}</p>;
      let input;
      return (
        <form
          onSubmit={(e) => {
            e.preventDefault();
            if (!input.value.trim()) return;
            addTodo({ variables: { text: input.value } })
              .then(() => (input.value = ""))
              .catch((err) => console.error(err));
          }}
        >
          <input type="text" ref={(node) => (input = node)} />
          <button type="submit" disabled={loading}>Add Todo</button>
        </form>
      );
    }}
  </Mutation>
);

export { TodoForm };

总结

优先解决graphql-tag的导入问题(当前报错的直接原因),再检查本地状态配置的完整性,确保addTodo的resolver逻辑正确,最后通过错误捕获辅助排查剩余问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:26:01