模拟方案功能
在服务器支持之前,先从客户端功能开始
如果你的GraphQL服务器还没有支持你的客户端将要使用的 字段,你仍然可以在客户端内模拟其行为,从而开始对该字段进行构建。
例如,假设我们想要把功能添加到来自全栈快速入门课程。具体来说,我们想要显示每次发射所使用的火箭的描述。为了在服务器端支持此功能,我们将在我们的模式中的description
字段Rocket
类型中添加一个:
type Rocket {id: ID!name: Stringtype: Stringdescription: String # field not yet supported}
但是,如果我们的后端团队还没有完成对 description
字段的支撑呢?通过模拟字段的行為,我們仍然可以在客戶端開始開發功能。要這樣做,我們將遵循以下步驟。
1. 定義客戶端架構(推薦)
我們的客戶端應用可以定義一個 客戶端架構,它從我們的伺服器擴展類型,甚至完全定義新類型。語法與伺服器端架構定義相同。
儘管客戶端架構對模拟不是 必需的,但它協助團隊成員瞭解您應用的局部功能。它還在工具如 Apollo Client Devtools 和 Apollo VS Code擴充插件 中啟用強大的局部狀態支持。
此客戶端架構將 Rocket
類型擴展以添加一個 description
字段(請確保將 變量 typeDefs
命名如下):
const typeDefs = gql`extend type Rocket {description: String}`;
我們可以這樣將此架構提供給 ApolloClient
架構師:
const client = new ApolloClient({uri: 'https://127.0.0.1:4000/graphql',cache: new InMemoryCache(),typeDefs});
2. 定義一個 read
函數
我们的客户端应用还不知道如何填充Rocket.description字段。为了解决这个问题,我们可以在 biztos
字段上定义一个read函数。 Apollo Client缓存会在查询字段时调用此函数,并使用函数的返回值作为字段的值。
现在,让我们在提供给InMemoryCache构造函数的配置对象中定义我们的read函数:
const cache = new InMemoryCache({typePolicies: {Rocket: {fields: {description: {read() { // Read function for Rocket.descriptionreturn 'Placeholder rocket description';}},},},},});
这让我们可以查询字段,但我们可能并不想为每枚火箭显示相同的样板描述。为了给我们的模拟输出增加多样性,我们可以使用像 faker.js这样的库:
import { faker } from "@faker-js/faker";// Returns 1 or 2 sentences of Lorem Ipsumconst oneOrTwoSentences = () =>faker.lorem.sentences(Math.random() < 0.5 ? 1 : 2);
然后,我们可以像这样更新我们的read函数:
// (within InMemoryCache constructor)read() {return oneOrTwoSentences();}
请确保只在您的开发构建中包含像faker.js这样的库,因为它们可能无端增加您的生产包大小。
3. 使用@client指令查询
我们已经准备好执行一个包含我们的新description字段的新GET_LAUNCH_DETAILS查询。以下是一个来自 full-stack quickstart的部分查询,我们添加了description字段:
export const GET_LAUNCH_DETAILS = gql`query LaunchDetails($launchId: ID!) {launch(id: $launchId) {siterocket {typedescription @client}}}`;
请注意,这个字段包含@client指令。此指令告诉 Apollo Client不要在我们的服务器发送的查询中包含description字段。这有两个相关的原因:
- description字段完全在本地填充,包含在网络请求中是无用的。
- description字段还没有在我们的服务器端模式中定义,包含它会产生 GraphQL错误。
我们现在可以像往常一样使用useQuery钩子在组件中执行这个查询:
export default function LaunchDetails({ launchId }) {const { data } = useQuery(GET_LAUNCH_DETAILS, { variables: { rocketId } });return (<div><p>Rocket Type: {data.launch.rocket.type}</p><p>Description: {data.launch.rocket.description}</p></div>);}
4. 准备好使用实时数据
当您的服务器准备好支持Rocket.description字段时,您可以通过以下操作开始使用它:
- 从包含它的每个查询中移除
@client
指令 和description
- 移除
read
字段的功能(或修改函数使其使用当前缓存的值而不是随机字符串)。
有关此处使用的Apollo客户端功能的更多信息,请参阅以下内容: