Skip to content

Commit 1afd830

Browse files
committed
Add useSyncGQLQuery hook.
1 parent d5a056e commit 1afd830

File tree

5 files changed

+89
-23
lines changed

5 files changed

+89
-23
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './sdk.ts';
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { useEffect } from 'react';
2+
import {
3+
useSyncState,
4+
useEventEffect,
5+
type ComponentEvent,
6+
type ReactiumSyncState,
7+
} from '@atomic-reactor/reactium-sdk-core';
8+
import {
9+
useLazyQuery,
10+
type OperationVariables,
11+
type DocumentNode,
12+
type TypedDocumentNode,
13+
type LazyQueryHookOptions,
14+
type QueryResult,
15+
type NoInfer,
16+
} from '@apollo/client';
17+
18+
/**
19+
* @description useSyncGQLQuery is a hook that wraps the useLazyQuery hook from Apollo Client, and adds state management and event handling.
20+
* @param {DocumentNode | TypedDocumentNode<TData, TVariables>} query The GraphQL query document.
21+
* @param {LazyQueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>} options Options to be passed to the useLazyQuery hook.
22+
* @param {'set' | 'change' | 'loaded' | 'refreshed' | string} [updateEvent='set'] The event name that triggers a rerender
23+
* @return {ReactiumSyncState<QueryResult<TData,TVariables>>} The sync state object.
24+
* @see {@link [useLazyQuery](https://www.apollographql.com/docs/react/api/react/hooks/#uselazyquery)} for more information on the useLazyQuery hook from which this hook is derived.
25+
* @see {@link [ReactiumSyncState](https://reactiumcore.github.io/reactium-sdk-core/classes/ReactiumSyncState.html)} to understand the underlying synchronized state object.
26+
*/
27+
export const useSyncGQLQuery = <
28+
TData = any,
29+
TVariables extends OperationVariables = OperationVariables,
30+
>(
31+
query: DocumentNode | TypedDocumentNode<TData, TVariables>,
32+
options?: LazyQueryHookOptions<NoInfer<TData>, NoInfer<TVariables>>,
33+
updateEvent: 'set' | 'change' | 'loaded' | 'refreshed' | string = 'set',
34+
): ReactiumSyncState<QueryResult<TData, TVariables>> => {
35+
const [lazy, result] = useLazyQuery(query, options);
36+
const state = useSyncState<typeof result>(result, updateEvent);
37+
38+
state.extend(
39+
'refresh',
40+
async (variables?: Partial<TVariables>): Promise<void> => {
41+
const vars = variables || options?.variables;
42+
state.dispatch('refresh');
43+
const newResponse = await result.refetch(vars);
44+
state.set(newResponse, undefined);
45+
state.dispatch<typeof newResponse>('refreshed', newResponse);
46+
},
47+
);
48+
49+
useEventEffect(state, {
50+
load: async (e): Promise<void> => {
51+
const { detail } = e as ComponentEvent<typeof options>;
52+
state.set('loading', true);
53+
const result = await lazy(detail);
54+
state.set(result, undefined);
55+
state.dispatch('loaded', result);
56+
},
57+
58+
refreshed: (e): void => {
59+
const { detail } = e as ComponentEvent<typeof result>;
60+
state.set(detail, undefined);
61+
},
62+
});
63+
64+
useEffect((): void => {
65+
if (result.called) return;
66+
state.dispatch('load', options);
67+
}, []);
68+
69+
return state;
70+
};

src/app/components/Dashboard/Dashboard.jsx

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,56 @@
1-
import { gql, useQuery } from '@apollo/client';
1+
import { gql, useLazyQuery } from '@apollo/client';
22
import Container from 'react-bootstrap/Container';
33
import Row from 'react-bootstrap/Row';
44
import Col from 'react-bootstrap/Col';
5-
import op from 'object-path';
6-
import { useEffect } from 'react';
75
import { useHookComponent } from 'reactium-core/sdk';
6+
import { useSyncGQLQuery } from '@reactium/graphql';
87

9-
const GET_USERS = gql`
10-
query {
8+
const LOAD_DASHBOARD_DATA = gql`
9+
query LoadDashboardDat($nums: [Int!]!) {
1110
users {
1211
id
1312
name
1413
email
1514
}
15+
1616
posts {
1717
id
1818
title
1919
body
2020
}
21+
22+
add(nums: $nums)
2123
}
2224
`;
2325

2426
export const Dashboard = () => {
2527
const PostList = useHookComponent('PostList');
2628
const UserList = useHookComponent('UserList');
2729

28-
const response = useQuery(GET_USERS);
29-
useEffect(() => {
30-
if (response.observable) {
31-
response.observable.subscribe({
32-
next: ({ data }) => {
33-
console.log({ data });
34-
},
35-
});
36-
}
37-
}, [response.observable]);
30+
const handle = useSyncGQLQuery(LOAD_DASHBOARD_DATA, {
31+
variables: { nums: [1, 2, 3, 5] },
32+
});
33+
window.handle = handle;
3834

39-
console.log({ response });
4035
return (
4136
<Container fluid as='main'>
42-
<h1>Dashboard</h1>
37+
<h1>Dashboard {handle.get('data.add')}</h1>
4338
<Row>
4439
<Col>
4540
<UserList
46-
{...response}
47-
users={op.get(response, 'data.users', [])}
41+
loading={handle.get('loading', false)}
42+
error={handle.get('error')}
43+
users={handle.get('data.users', [])}
4844
/>
4945
</Col>
5046
</Row>
5147

5248
<Row>
5349
<Col>
5450
<PostList
55-
{...response}
56-
posts={op.get(response, 'data.posts', [])}
51+
loading={handle.get('loading', false)}
52+
error={handle.get('error')}
53+
posts={handle.get('data.posts', [])}
5754
/>
5855
</Col>
5956
</Row>

src/app/components/Dashboard/Post/PostList/PostList.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Table from 'react-bootstrap/Table';
55
import Placeholder from 'react-bootstrap/Placeholder';
66

77
export const PostList = ({ loading = true, error, posts = [] }) => {
8-
console.log({ loading, error, posts });
98
return (
109
<Accordion defaultActiveKey='0' className='posts'>
1110
<Accordion.Item eventKey='0'>

src/app/components/Dashboard/User/UserList/UserList.jsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import Table from 'react-bootstrap/Table';
55
import Placeholder from 'react-bootstrap/Placeholder';
66

77
export const UserList = ({ loading = true, error, users = [] }) => {
8-
console.log({ loading, error, users });
98
return (
109
<Accordion defaultActiveKey='0' className='users'>
1110
<Accordion.Item eventKey='0'>

0 commit comments

Comments
 (0)