前端GraphQL客户端:优雅地获取数据

张开发
2026/4/4 8:58:52 15 分钟阅读
前端GraphQL客户端:优雅地获取数据
前端GraphQL客户端优雅地获取数据毒舌时刻前端GraphQL这不是后端的事吗REST API就够了为什么要用GraphQL——结果前端需要多次请求数据冗余GraphQL太复杂了我学不会——结果错过了更灵活的数据获取方式我直接用fetch请求GraphQL多简单——结果缺少缓存、错误处理等功能。醒醒吧GraphQL不是后端的专利前端也需要专业的客户端工具为什么你需要这个减少网络请求一次请求获取所有需要的数据数据精确只获取需要的数据避免冗余类型安全自动生成TypeScript类型缓存优化智能缓存减少重复请求开发效率简化数据获取逻辑反面教材// 反面教材直接使用fetch请求GraphQL async function fetchGraphQL(query, variables) { const response await fetch(https://api.example.com/graphql, { method: POST, headers: { Content-Type: application/json, }, body: JSON.stringify({ query, variables }), }); const data await response.json(); if (data.errors) { console.error(GraphQL errors:, data.errors); throw new Error(GraphQL request failed); } return data.data; } // 反面教材重复请求相同数据 async function loadUserAndPosts() { // 第一次请求用户信息 const { user } await fetchGraphQL( query GetUser($id: ID!) { user(id: $id) { id name email } } , { id: 1 }); // 第二次请求用户的帖子 const { user: userWithPosts } await fetchGraphQL( query GetUserWithPosts($id: ID!) { user(id: $id) { id posts { id title content } } } , { id: 1 }); return { user, posts: userWithPosts.posts }; }正确的做法// 正确的做法使用Apollo Client import { ApolloClient, InMemoryCache, gql } from apollo/client; // 创建Apollo Client实例 const client new ApolloClient({ uri: https://api.example.com/graphql, cache: new InMemoryCache(), headers: { authorization: localStorage.getItem(token) || } }); // 定义查询 const GET_USER_WITH_POSTS gql query GetUserWithPosts($id: ID!) { user(id: $id) { id name email posts { id title content createdAt } } } ; // 定义变更 const CREATE_POST gql mutation CreatePost($input: PostInput!) { createPost(input: $input) { id title content createdAt } } ; // 在React组件中使用 import React from react; import { useQuery, useMutation } from apollo/client; function UserProfile({ userId }) { // 使用useQuery钩子获取数据 const { loading, error, data, refetch } useQuery(GET_USER_WITH_POSTS, { variables: { id: userId }, // 缓存策略 fetchPolicy: cache-and-network }); // 使用useMutation钩子执行变更 const [createPost, { loading: creating }] useMutation(CREATE_POST, { // 变更后更新缓存 update(cache, { data: { createPost } }) { const { user } cache.readQuery({ query: GET_USER_WITH_POSTS, variables: { id: userId } }); cache.writeQuery({ query: GET_USER_WITH_POSTS, variables: { id: userId }, data: { user: { ...user, posts: [...user.posts, createPost] } } }); } }); if (loading) return div加载中.../div; if (error) return div错误{error.message}/div; const handleCreatePost async (title, content) { await createPost({ variables: { input: { title, content, userId } } }); }; return ( div h2{data.user.name}/h2 p{data.user.email}/p h3帖子/h3 ul {data.user.posts.map(post ( li key{post.id} h4{post.title}/h4 p{post.content}/p p{post.createdAt}/p /li ))} /ul button onClick{() refetch()}刷新/button button onClick{() handleCreatePost(新帖子, 帖子内容)} disabled{creating} {creating ? 创建中... : 创建帖子} /button /div ); } // 正确的做法使用URQL import { createClient, gql } from urql; // 创建URQL客户端 const client createClient({ url: https://api.example.com/graphql, fetchOptions: () ({ headers: { authorization: localStorage.getItem(token) || } }) }); // 在React组件中使用 import React from react; import { useQuery, useMutation } from urql; function UserList() { const [result, reexecuteQuery] useQuery({ query: gql query GetUsers { users { id name email } } }); const { data, fetching, error } result; if (fetching) return div加载中.../div; if (error) return div错误{error.message}/div; return ( div h2用户列表/h2 ul {data.users.map(user ( li key{user.id} {user.name} - {user.email} /li ))} /ul button onClick{() reexecuteQuery()}刷新/button /div ); } // 正确的做法使用Relay import { Environment, Network, RecordSource, Store, useLazyLoadQuery, graphql } from relay-runtime; // 创建Relay环境 function fetchQuery(operation, variables) { return fetch(https://api.example.com/graphql, { method: POST, headers: { Content-Type: application/json, authorization: localStorage.getItem(token) || }, body: JSON.stringify({ query: operation.text, variables, }), }).then(response { return response.json(); }); } const environment new Environment({ network: Network.create(fetchQuery), store: new Store(new RecordSource()), }); // 定义查询 const UserQuery graphql query UserQuery($id: ID!) { user(id: $id) { id name email posts { edges { node { id title content } } } } } ; // 在React组件中使用 function UserDetail({ userId }) { const data useLazyLoadQuery( UserQuery, { id: userId } ); return ( div h2{data.user.name}/h2 p{data.user.email}/p h3帖子/h3 ul {data.user.posts.edges.map(edge ( li key{edge.node.id} h4{edge.node.title}/h4 p{edge.node.content}/p /li ))} /ul /div ); }毒舌点评看看这才叫前端GraphQL客户端不是简单地使用fetch请求而是使用Apollo Client、URQL或Relay等专业的客户端工具。记住GraphQL客户端不仅仅是发送请求还包括缓存管理、错误处理、类型生成等功能。这些工具可以大大简化你的前端代码提高开发效率。所以别再觉得GraphQL复杂了使用专业的客户端工具让数据获取变得更加优雅总结Apollo Client功能强大生态丰富适合大型应用URQL轻量级API简洁适合中小型应用RelayFacebook开发性能优异适合大型应用缓存管理智能缓存减少重复请求类型安全自动生成TypeScript类型错误处理统一的错误处理机制变更管理执行GraphQL变更并更新缓存开发工具GraphQL Playground、Apollo DevTools等前端GraphQL客户端让数据获取变得更加优雅

更多文章