10月8日至10日,与我们相聚纽约市,了解关于 GraphQL 联邦和 API 平台工程的最新的技巧、趋势和新闻。参加纽约市2024年 GraphQL 峰会
文档
免费开始

与 Apollo 客户端的 React Context

通过使用 React 钩子使数据可访问来避免 prop 钻孔

客户端

React Context 通过无需在应用程序的每一级手动传递 props 即可传递数据的方式,在组件树中通过上下文进行数据传递,这种方式也被称为 prop 钻孔。

当您需要重命名属性或更新数据类型时,prop 钻孔可能会导致问题,并且会随着树中每个组件都需要知道它们可能不使用的属性而使应用程序变得臃肿。相反,我们的数据将通过一个 React 钩子来访问,这个钩子可以在嵌套组件树的任何地方调用。

为了帮助展示如何避免 prop 钻孔,我们将首先配置两个组件使用 React ContextQueryResultProvideruseQueryResult

组件 QueryResultProvider 用于封装一个组件树,为特定 提供 查询,这是一个 查询,并且可选地 变量 传递给查询。该组件通过从 获取 useQuery 钩子执行 查询 并获取查询数据、加载和错误值。然后这些值将被保存在上下文中。

import React, { createContext, useContext } from "react";
import { ApolloQueryResult, OperationVariables, useQuery } from "@apollo/client";
interface QueryResult<TData> {
data?: TData;
error?: any;
loading: boolean;
}
interface QueryContextValue<TData> {
queryData: QueryResult<TData>;
refetch: () => Promise<ApolloQueryResult<TData>>;
}
const QueryResultContext = createContext<QueryContextValue<any>>({
queryData: { loading: true },
refetch: () => Promise.resolve({} as ApolloQueryResult<any>),
});
interface QueryResultProviderProps<TVariables extends OperationVariables | undefined = object> {
query: any;
variables?: TVariables;
children: React.ReactNode;
}
export const QueryResultProvider = ({ query, variables, children }: QueryResultProviderProps) => {
const { data, error, loading, refetch } = useQuery(query, { variables });
const value = { queryData: { data, error, loading }, refetch };
return <QueryResultContext.Provider value={value}>{children}</QueryResultContext.Provider>;
};
export const useQueryResult = <TData = any,>(): QueryResult<TData> => {
const context = useContext(QueryResultContext);
if (!context) {
throw new Error("useQueryResult must be used within a QueryResultProvider");
}
return context.queryData;
};

在此示例中,我们使用QueryResultProvider组件包装Users组件,向其提供GET_USERS查询。然后Users组件使用useQueryResult钩子从查询上下文访问数据、加载状态和错误。

import { QueryResultProvider, useQueryResult } from "./query-context";
import { gql } from "@apollo/client";
const GET_USERS = gql`
query GetUsers {
users {
id
name
}
}
`;
interface IUser {
id: string;
name: string;
}
const Users = () => {
const { data, loading, error } = useQueryResult<IUser>();
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>Users</h1>
<ul>
{data.users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
</div>
);
};
const App = () => (
<QueryResultProvider query={GET_USERS}>
<Users />
</QueryResultProvider>
);
下一步
首页
评分文章评分在GitHub上编辑编辑论坛Discord

©2024Apollo Graph Inc.,称作Apollo GraphQL。

隐私政策

公司