衍生欄位
除了對客戶端狀態建模之外,Relay 解析器還允許您定義欄位,這些欄位是其他欄位的純函數。這些欄位稱為衍生欄位,可以定義在任何類型上,無論是在伺服器還是客戶端上定義。
對於全域相關的資料,解析器相較於其他解決方案(如React Hooks)有一些優勢
- 全域記憶化 - Relay 解析器會自動記憶化衍生欄位。與 Hook 不同,此快取由應用程式中的所有元件共享,因此如果兩個同級元件都讀取相同的欄位,則計算只會執行一次。
- 高效更新 - 如果您的衍生解析器重新計算但得出相同的值,Relay 可以避免重新渲染讀取該欄位的元件。
- 可組合 - 衍生欄位可以與其他衍生欄位組合,讓您可以建立複雜但明確的計算圖。
- 可探索 - 圖中的值可以透過 GraphQL 結構探索,因此更可能被發現和重複使用,而不是重新發明。
- 已記錄 - GraphQL 的欄位文件和結構化棄用模型使您可以輕鬆理解欄位的用途及其預期用途。
定義衍生解析器
衍生解析器看起來像任何其他解析器,除了它們讀取 GraphQL 資料,而不是從父模型類型計算。衍生解析器透過定義「根片段」來讀取 GraphQL 資料,該片段是在欄位的父類型上定義的 GraphQL 片段。
根片段是使用 @rootFragment
docblock 標籤後跟片段名稱來定義的。這會告知 Relay 將該片段的片段鍵傳遞給解析器函式。然後可以使用從 relay-runtime
匯入的 readFragment
讀取片段資料。
- Docblock
import {readFragment} from 'relay-runtime';
/**
* @RelayResolver User.fullName: String
* @rootFragment UserFullNameFragment
*/
export function fullName(key: UserFullNameFragment$key): string {
const user = readFragment(graphql`
fragment UserFullNameFragment on User {
firstName
lastName
}
`, key);
return `${user.firstName} ${user.lastName}`;
}
資訊
Relay 將追蹤從片段讀取的所有值,並在任何這些值變更時自動重新計算解析器。
組合
衍生解析器的一個強大功能是它們可以讀取其他 Relay 解析器欄位。這表示您可以定義一個衍生解析器,它結合了伺服器資料、客戶端資料,甚至是其他衍生解析器。這讓您可以建立複雜但明確的計算圖。
/**
* @RelayResolver CheckoutItem.isValid: Boolean
* @rootFragment CheckoutItemFragment
*/
export function isValid(key): boolean {
const item = readFragment(graphql`
fragment CheckoutItemFragment on CheckoutItem {
product {
price
}
quantity
}
`, key);
return item.product.price * item.quantity > 0;
}
/**
* @RelayResolver ShoppingCart.canCheckout: Boolean
* @rootFragment ShoppingCartFragment
*/
export function canCheckout(key): boolean {
const cart = readFragment(graphql`
fragment ShoppingCartFragment on ShoppingCart {
items {
isValid
}
}
`, key);
return cart.items.every(item => item.isValid);
}
將引數傳遞給您的 @rootFragment
如果衍生解析器的根片段中的欄位需要引數,您可以透過將 @arguments
標籤新增至 docblock 標籤來傳遞它們。@argument
標籤採用引數的名稱和引數的類型。引數類型必須是有效的 GraphQL 輸入類型。有關引數和解析器的更多資訊,請參閱欄位引數。