React 用 urql 接入 GraphQL:类型安全的查询、缓存与错误边界

test12026-11-031 次阅读

为什么在 React 里选 urql

GraphQL 客户端不止 Apollo 一个选择。urql 的核心优势是体积小、默认带归一化缓存、扩展靠插件。它的心智模型只有三样东西:Provider 提供客户端、useQuery 取数据、useMutation 改数据。相比 Apollo 全家桶,urql 把逻辑留在你自己的代码里,而不是塞进一个庞大状态机。

安装与 Provider 配置

先用包管理器装上核心库和缓存、交换层。Exchange 是 urql 的中间件链,fetchExchange 负责真正发请求,cacheExchange 负责归一化缓存。

npm install urql graphql @urql/exchange-graphcache
import { Client, Provider, cacheExchange, fetchExchange } from 'urql';

const client = new Client({
  url: 'https://api.example.com/graphql',
  exchanges: [cacheExchange, fetchExchange],
});

export default function App() {
  return (
    <Provider value={client}>
      <UserList />
    </Provider>
  );
}

用 graphql-code-generator 生成类型

手写 GraphQL 字符串容易和后端字段对不上。用 codegen 把 schema 拉下来,生成 TS 类型,查询变量和返回结构都有提示。

// codegen.ts
import type { CodegenConfig } from '@graphql-codegen/cli';

const config: CodegenConfig = {
  schema: 'https://api.example.com/graphql',
  generates: {
    'src/gql/': {
      documents: 'src/**/*.tsx',
      plugins: ['typescript', 'typescript-operations', 'typed-document-node'],
    },
  },
};

export default config;

发起查询并消费缓存

useQuery 返回 data、fetching(加载态)、error。同一份查询在多个组件里调用,urql 只会发一次网络请求,其余命中缓存。

import { useQuery, gql } from 'urql';

const USERS = gql`
  query Users($first: Int!) {
    users(first: $first) {
      id
      name
      email
    }
  }
`;

function UserList() {
  const [{ data, fetching, error }] = useQuery({
    query: USERS,
    variables: { first: 10 },
  });

  if (fetching) return <p>加载中</p>;
  if (error) return <p>出错了:{error.message}</p>;

  return (
    <ul>
      {data.users.map((u) => (
        <li key={u.id}>{u.name} &lt;{u.email}&gt;</li>
      ))}
    </ul>
  );
}

写操作与乐观更新

useMutation 负责变更。配合 cache 的 optimistic 配置,可以先把预期结果写进缓存,等服务器确认后再替换,列表瞬间更新。

import { useMutation, gql } from 'urql';

const ADD_USER = gql`
  mutation AddUser($name: String!, $email: String!) {
    addUser(name: $name, email: $email) {
      id
      name
    }
  }
`;

function AddForm() {
  const [, addUser] = useMutation(ADD_USER);

  async function onSubmit(name: string, email: string) {
    const res = await addUser({ name, email });
    if (res.error) {
      console.error(res.error.message);
    }
  }

  return <button onClick={() => onSubmit('张三', 'zhang@example.com')}>新增</button>;
}

小结

urql 适合想要轻量、可预测缓存、又不想被框架绑死的项目。配合 graphql-code-generator 拿到端到端类型,查询与变更都能在编译期发现问题。缓存、重试、持久化这些能力都通过 exchange 插件叠加,扩展时不会污染业务组件。

T

test1

文章作者

为什么在 React 里选 urql GraphQL 客户端不止 Apollo 一个选择。urql 的核心优势是体积小...

分类
技术
发布时间
2026-11-03
字数
约 2491 字
阅读
1 次