GraphQL 查詢
可以使用 graphQLSelector()
和 graphQLSelectorFamily()
來執行 GraphQL 查詢。(透過 原子效果 提供基礎支援)。但首先,請務必 設定 Relay 環境。
簡單的 GraphQL 查詢
graphQLSelector()
可用於建立與 GraphQL 查詢 同步的選取器。此選取器有助於使 GraphQL 查詢與 Recoil 資料流程圖保持同步。它可以仰賴上游的 Recoil 原子/選取器,以決定要針對 GraphQL 查詢使用的 變數
或轉換結果。對於 Relay GraphQL 狀態的任何 變異、局部更新、遞延資料 或 即時查詢 也會自動與選取器同步並導致其更新。這允許您將伺服器視為事實來源,並將選取器作為本地快取。
const userNameQuery = graphQLSelector({
key: 'UserName',
environment: myEnvironmentKey,
query: graphql`
query UserNameQuery($id: ID!) {
user(id: $id) {
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data.user?.name,
});
function MyComponent() {
const seenCount = useRecoilValue(seenCountQuery);
return <span>{seenCount}</span>;
}
除了使用其他上游原子/選取器來計算 GraphQL 查詢變數之外,下游選取器也可以使用 graphQLSelector()
來提供衍生狀態。
const pictureForUserState = selector({
key: 'PictureForUser',
get: async ({get}) => {
const username = get(userNameQuery);
const picture = await fetch(urlForUserNamePicture(username));
return picture;
},
});
參數化的 GraphQL 查詢
graphQLSelectorFamily()
允許您使用參數加上其他 Recoil 狀態來計算查詢變數。參數可以根據組件的道具、React 狀態、用於其他 Recoil 選擇器等因素決定。
const userQuery = graphQLSelectorFamily({
key: 'UserQuery',
environment: myEnvironmentKey,
query: graphql`
query UserQuery($id: ID!, $clientID: ClientID!) {
user(id: $id, client_id: $clientID) {
name
address
}
}
`,
variables: id => ({get}) => ({id, clientID: get(clientIDAtom}),
mapResponse: data => data.user,
});
function MyComponent(props) {
const user = useRecoilValue(userQuery(props.userID));
return (
<div>
<h1>{user.name}</h1>
</div>
);
}
GraphQL 片段
GraphQL 查詢也可以透過 @inline
指令和 readInlineData()
,包含 GraphQL 片段。
const userNameFragment = graphql`
fragment UserNameFragment on User @inline {
name
}
`;
import {readInlineData} from 'relay-runtime';
const userNameQuery = graphQLSelectorFamily({
key: 'UserNameQuery',
environment: myEnvironmentKey,
query: graphql`
query UserNameQuery($id: ID!) {
user(id: $id) {
...UserNameFragment
}
}
`,
variables: id => ({id}),
mapResponse: response => {
const userFragment = readInlineData(userNameFragment, response.user);
return userFragment?.name;
},
})
預取 GraphQL
GraphQL 查詢也可以使用 預取模式 進行預取。
function CurrentUserInfo() {
const currentUserID = useRecoilValue(currentUserIDState);
const userInfo = useRecoilValue(userInfoQuery(currentUserID));
const changeUser = useRecoilCallback(({snapshot, set}) => userID => {
// pre-fetch user info
snapshot.getLoadable(userInfoQuery(userID));
// change current user to start new render
set(currentUserIDState, userID);
});
return (
<div>
<h1>{userInfo.name}</h1>
<ul>
{userInfo.friends.map(friend =>
<li key={friend.id} onClick={() => changeUser(friend.id)}>
{friend.name}
</li>
)}
</ul>
</div>
);
}
預載 GraphQL
如果您使用的是 EntryPoints,那麼您可以預載查詢與載入頁面大部分 JS 同步執行。
首先,請確定您在應用程式根目錄為預載查詢 註冊了一個 EnvironmentKey
export const preloadedEnvironmentKey = new EnvironmentKey('preloaded');
export function AppRoot() {
const preloadedEnvironment = useRelayEnvironment();
return (
<RecoilRoot>
<RecoilRelayEnvironment
environmentKey={preloadedEnvironmentKey}
environment={preloadedEnvironment}>
{/* My App */}
</RecoilRelayEnvironment>
</RecoilRoot>
)
}
然後,將您的查詢引導至使用此 preloadedEnvironmentKey
並將 @preloadable
裝飾器加入 GraphQL
export const userQuery = graphQLSelector({
key: 'UserQuery',
environmentKey: preloadedEnvironmentKey,
query: graphql`
query UserQuery($id: ID!) @preloadable {
user(id: $id) {
name
}
}
`,
variables: ({get}) => ({id: get(currentIDAtom)}),
mapResponse: data => data?.user,
});
最後,將此查詢新增到 *.entrypoint.js
檔案中的預載查詢中
const MyEntryPoint = {
getPreloadProps: params => ({
queries: {
userQuery: {
parameters: require('UserQuery$Parameters'),
variables: {id: params.id},
},
}),
root: JSResource('m#MyApp.react'),
};