diff --git a/example/components/AccountMembership.tsx b/example/components/AccountMembership.tsx index 0e5de4f..ef5fdff 100644 --- a/example/components/AccountMembership.tsx +++ b/example/components/AccountMembership.tsx @@ -1,6 +1,8 @@ import { FragmentOf, readFragment } from "gql.tada"; +import { useState } from "react"; import { P, match } from "ts-pattern"; import { graphql } from "../graphql"; +import { AccountMembershipDetail } from "./AccountMembershipDetail"; export const accountMembershipFragment = graphql(` fragment AccountMembership on AccountMembership { @@ -35,27 +37,37 @@ type Props = { export const AccountMembership = ({ data }: Props) => { const accountMembership = readFragment(accountMembershipFragment, data); + const [isOpen, setIsOpen] = useState(false); + return ( -
- {accountMembership.id}: - {match(accountMembership) - .with( - { user: { firstName: P.string, lastName: P.string } }, - ({ user: { firstName, lastName } }) => `${firstName} ${lastName}`, - ) - .with( - { - statusInfo: { - restrictedTo: { firstName: P.string, lastName: P.string }, - }, - }, - ({ - statusInfo: { - restrictedTo: { firstName, lastName }, + <> +
setIsOpen(true)}> + {accountMembership.id}: + {match(accountMembership) + .with( + { user: { firstName: P.string, lastName: P.string } }, + ({ user: { firstName, lastName } }) => `${firstName} ${lastName}`, + ) + .with( + { + statusInfo: { + restrictedTo: { firstName: P.string, lastName: P.string }, + }, }, - }) => `${firstName} ${lastName} (restricted to)`, - ) - .otherwise(() => "No user")} -
+ ({ + statusInfo: { + restrictedTo: { firstName, lastName }, + }, + }) => `${firstName} ${lastName} (restricted to)`, + ) + .otherwise(() => "No user")} +
+ {isOpen ? ( + setIsOpen(false)} + /> + ) : null} + ); }; diff --git a/example/components/AccountMembershipDetail.tsx b/example/components/AccountMembershipDetail.tsx new file mode 100644 index 0000000..cf0c9eb --- /dev/null +++ b/example/components/AccountMembershipDetail.tsx @@ -0,0 +1,70 @@ +import { AsyncData, Result } from "@swan-io/boxed"; +import { useState } from "react"; +import { P, match } from "ts-pattern"; +import { ClientError, useQuery } from "../../src"; +import { graphql } from "../graphql"; +import { UserCard } from "./UserCard"; + +export const accountMembershipDetailQuery = graphql(` + query AccountMembershipDetail($accountMembershipId: ID!) { + accountMembership(id: $accountMembershipId) { + id + user { + id + firstName + lastName + } + } + } +`); + +type Props = { + accountMembershipId: string; + onPressClose: () => void; +}; + +export const AccountMembershipDetail = ({ + accountMembershipId, + onPressClose, +}: Props) => { + const [data] = useQuery( + accountMembershipDetailQuery, + { accountMembershipId }, + { optimize: true }, + ); + + const [showDetails, setShowDetails] = useState(false); + + return match(data) + .with(AsyncData.P.NotAsked, () => "Nothing") + .with(AsyncData.P.Loading, () => "Loading") + .with(AsyncData.P.Done(Result.P.Error(P.select())), (error) => { + ClientError.forEach(error, (error) => console.error(error)); + return "Error"; + }) + .with( + AsyncData.P.Done(Result.P.Ok(P.select())), + ({ accountMembership }) => { + if (accountMembership == null) { + return
No membership
; + } + return ( + + +
+ Membership: {accountMembership.id} + + {showDetails ? ( + + ) : ( + + )} +
+
+ ); + }, + ) + .exhaustive(); +}; diff --git a/example/components/UserCard.tsx b/example/components/UserCard.tsx new file mode 100644 index 0000000..fa7a64f --- /dev/null +++ b/example/components/UserCard.tsx @@ -0,0 +1,80 @@ +import { AsyncData, Result } from "@swan-io/boxed"; +import { P, match } from "ts-pattern"; +import { ClientError, useQuery } from "../../src"; +import { graphql } from "../graphql"; + +export const accountMembershipUserDetailQuery = graphql(` + query AccountMembershipUserDetail($accountMembershipId: ID!) { + accountMembership(id: $accountMembershipId) { + id + user { + id + firstName + lastName + birthDate + mobilePhoneNumber + } + } + } +`); + +type Props = { + accountMembershipId: string; +}; + +const formatter = new Intl.DateTimeFormat(); + +export const UserCard = ({ accountMembershipId }: Props) => { + const [data] = useQuery( + accountMembershipUserDetailQuery, + { + accountMembershipId, + }, + { optimize: true }, + ); + + return match(data) + .with(AsyncData.P.NotAsked, () => "Nothing") + .with(AsyncData.P.Loading, () => "Loading") + .with(AsyncData.P.Done(Result.P.Error(P.select())), (error) => { + ClientError.forEach(error, (error) => console.error(error)); + return "Error"; + }) + .with( + AsyncData.P.Done(Result.P.Ok(P.select())), + ({ accountMembership }) => { + if (accountMembership == null) { + return null; + } + const user = accountMembership.user; + if (user == null) { + return
No user
; + } + return ( +
+ +
+ ); + }, + ) + .exhaustive(); +}; diff --git a/example/graphql.ts b/example/graphql.ts index 6e20c13..3da56b1 100644 --- a/example/graphql.ts +++ b/example/graphql.ts @@ -7,5 +7,7 @@ export const graphql = initGraphQLTada<{ ID: string; Currency: string; AmountValue: string; + Date: string; + PhoneNumber: string; }; }>(); diff --git a/src/client.ts b/src/client.ts index f2a510a..c594bca 100644 --- a/src/client.ts +++ b/src/client.ts @@ -164,7 +164,7 @@ export class Client { variablesAsRecord, ); if (operationResult.isSome()) { - return Future.value(operationResult.get()); + return Future.value(operationResult.get() as Result); } } diff --git a/src/react/useQuery.ts b/src/react/useQuery.ts index 4082089..92abd5d 100644 --- a/src/react/useQuery.ts +++ b/src/react/useQuery.ts @@ -83,7 +83,7 @@ export const useQuery = ( } const request = client.query(stableQuery, stableVariables, { optimize }); return () => request.cancel(); - }, [client, suspense, stableQuery, stableVariables]); + }, [client, suspense, optimize, stableQuery, stableVariables]); const [isRefreshing, setIsRefreshing] = useState(false); const refresh = useCallback(() => {