@trackunit/react-graphql-hooks 1.3.48 → 1.3.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.cjs.js +60 -32
  2. package/index.esm.js +61 -33
  3. package/package.json +4 -4
package/index.cjs.js CHANGED
@@ -141,16 +141,22 @@ const usePaginationQuery = (document, { ...props }) => {
141
141
  // Before, it required variables to always be memorized in the parent which was easy to forget and confusing.
142
142
  // Maybe better solution exists but this is the best I could come up with without changing to much.
143
143
  // If ever a better solution is found, please remove this ugliness.
144
- const stableVariables = react.useRef(props.variables);
145
- const internalProps = react.useMemo(() => {
146
- if (!isEqual(props.variables, stableVariables.current)) {
147
- stableVariables.current = props.variables;
144
+ const [stableVariables, setStableVariables] = react.useState(props.variables);
145
+ // Use ref for variables comparison to avoid setState inside useMemo
146
+ const variablesRef = react.useRef(props.variables);
147
+ // Use effect to update the ref when props.variables changes
148
+ react.useEffect(() => {
149
+ if (!isEqual(props.variables, variablesRef.current)) {
150
+ variablesRef.current = props.variables;
151
+ setStableVariables(props.variables);
148
152
  }
153
+ }, [props.variables]);
154
+ const internalProps = react.useMemo(() => {
149
155
  return {
150
156
  ...props,
151
- variables: stableVariables.current,
157
+ variables: stableVariables,
152
158
  };
153
- }, [props]);
159
+ }, [props, stableVariables]);
154
160
  const [, { fetchMore, networkStatus }] = ApolloClient__namespace.useLazyQuery(document, {
155
161
  ...internalProps,
156
162
  context: {
@@ -177,7 +183,7 @@ const usePaginationQuery = (document, { ...props }) => {
177
183
  const onReset = react.useCallback(() => {
178
184
  setResetTrigger(prev => prev + 1);
179
185
  }, []);
180
- const { table: { setIsLoading, isLoading, setPageInfo, pageInfo, reset, nextPage, previousPage }, variables: { first, after }, } = reactTablePagination.useRelayPagination({
186
+ const { table: { setIsLoading, isLoading, setPageInfo, pageInfo, reset, nextPage, previousPage }, variables: { first, after, last, before }, } = reactTablePagination.useRelayPagination({
181
187
  pageSize: internalProps.pageSize || internalProps.variables?.first || reactTablePagination.defaultPageSize,
182
188
  onReset,
183
189
  });
@@ -189,7 +195,7 @@ const usePaginationQuery = (document, { ...props }) => {
189
195
  /**
190
196
  * To support pagination with page and pageSize, we need to convert the variables from first and after.
191
197
  */
192
- let fetchMoreVariables = {
198
+ const fetchMoreVariables = {
193
199
  ...internalProps.variables,
194
200
  ...(internalProps.variables && "page" in internalProps.variables && "pageSize" in internalProps.variables
195
201
  ? // eslint-disable-next-line local-rules/no-typescript-assertion
@@ -199,37 +205,25 @@ const usePaginationQuery = (document, { ...props }) => {
199
205
  }
200
206
  : { ...variables }),
201
207
  };
202
- // To support "pageable" queries we do it here! REMOVE once the serviceplans are updated to use the new pagination.
203
- fetchMoreVariables = {
204
- ...("pageable" in fetchMoreVariables
205
- ? {
206
- ...fetchMoreVariables,
207
- pageable: {
208
- first: fetchMoreVariables.first,
209
- last: fetchMoreVariables.last,
210
- before: fetchMoreVariables.before,
211
- after: fetchMoreVariables.after,
212
- pageSize: fetchMoreVariables.pageSize,
213
- },
214
- }
215
- : { ...fetchMoreVariables }),
216
- };
217
208
  fetchMore({
218
209
  variables: fetchMoreVariables,
219
- updateQuery: (_, { fetchMoreResult }) => {
210
+ updateQuery: (previousResult, { fetchMoreResult }) => {
220
211
  if (abortController.signal.aborted) {
221
212
  // if prev does not hold any data we don't want to return it,
222
213
  // since it will make the cache output an error to the console.
223
214
  // https://github.com/apollographql/apollo-client/issues/8677
224
215
  if (prev) {
225
- // eslint-disable-next-line local-rules/no-typescript-assertion
226
- return sharedUtils.objectKeys(prev).length === 0 ? undefined : prev;
216
+ return sharedUtils.objectKeys(prev).length === 0
217
+ ? undefined
218
+ : prev;
227
219
  }
228
220
  // eslint-disable-next-line local-rules/no-typescript-assertion
229
221
  return undefined;
230
222
  }
231
- setLastFetchedData(fetchMoreResult);
232
- const result = internalProps.updateQuery(prev, fetchMoreResult);
223
+ // Safely handle Apollo types
224
+ const typedResult = fetchMoreResult;
225
+ setLastFetchedData(typedResult);
226
+ const result = internalProps.updateQuery(prev, typedResult);
233
227
  setPageInfo(result.pageInfo || null);
234
228
  setData(result.data);
235
229
  setIsLoading(false);
@@ -254,15 +248,49 @@ const usePaginationQuery = (document, { ...props }) => {
254
248
  setData(undefined);
255
249
  reset();
256
250
  }, [internalProps.variables, reset]);
251
+ // Use a ref to track the current value of first variable
252
+ const lastRef = react.useRef(last);
253
+ react.useEffect(() => {
254
+ lastRef.current = last;
255
+ }, [last]);
256
+ const beforeRef = react.useRef(before);
257
257
  react.useEffect(() => {
258
- doFetchMore({ first, last: undefined, before: undefined, after: undefined }, undefined);
259
- // eslint-disable-next-line react-hooks/exhaustive-deps
258
+ beforeRef.current = before;
259
+ }, [before]);
260
+ const firstRef = react.useRef(first);
261
+ react.useEffect(() => {
262
+ firstRef.current = first;
263
+ }, [first]);
264
+ // Use a ref to track the current data
265
+ const dataRef = react.useRef(data);
266
+ react.useEffect(() => {
267
+ dataRef.current = data;
268
+ }, [data]);
269
+ // Store doFetchMore in a ref to avoid dependency cycles
270
+ const doFetchMoreRef = react.useRef(doFetchMore);
271
+ react.useEffect(() => {
272
+ doFetchMoreRef.current = doFetchMore;
273
+ }, [doFetchMore]);
274
+ // Stabilize the fetchMore call by using refs instead of direct dependencies
275
+ react.useEffect(() => {
276
+ const fetchVariables = {
277
+ first: firstRef.current,
278
+ last: undefined,
279
+ before: undefined,
280
+ after: undefined,
281
+ };
282
+ // Use the ref version to avoid dependency cycles
283
+ doFetchMoreRef.current(fetchVariables, undefined);
284
+ // Removed doFetchMore from dependencies to prevent refetch loops
260
285
  }, [internalProps.variables, resetTrigger]);
286
+ // Stabilize the pagination effect
261
287
  react.useEffect(() => {
262
288
  if (after) {
263
- doFetchMore({ first, after }, data);
289
+ const fetchVariables = { first: firstRef.current, after, last: lastRef.current, before: beforeRef.current };
290
+ // Use the ref version to avoid dependency cycles
291
+ doFetchMoreRef.current(fetchVariables, dataRef.current);
264
292
  }
265
- // eslint-disable-next-line react-hooks/exhaustive-deps
293
+ // Removed doFetchMore from dependencies to prevent refetch loops
266
294
  }, [after]);
267
295
  return react.useMemo(() => {
268
296
  return {
package/index.esm.js CHANGED
@@ -4,7 +4,7 @@ import { truthy, objectKeys } from '@trackunit/shared-utils';
4
4
  import * as ApolloClient from '@apollo/client';
5
5
  import { useRelayPagination, defaultPageSize } from '@trackunit/react-table-pagination';
6
6
  import isEqual from 'lodash/isEqual';
7
- import { useState, useRef, useMemo, useCallback, useEffect } from 'react';
7
+ import { useState, useRef, useEffect, useMemo, useCallback } from 'react';
8
8
 
9
9
  var defaultTranslations = {
10
10
 
@@ -120,16 +120,22 @@ const usePaginationQuery = (document, { ...props }) => {
120
120
  // Before, it required variables to always be memorized in the parent which was easy to forget and confusing.
121
121
  // Maybe better solution exists but this is the best I could come up with without changing to much.
122
122
  // If ever a better solution is found, please remove this ugliness.
123
- const stableVariables = useRef(props.variables);
124
- const internalProps = useMemo(() => {
125
- if (!isEqual(props.variables, stableVariables.current)) {
126
- stableVariables.current = props.variables;
123
+ const [stableVariables, setStableVariables] = useState(props.variables);
124
+ // Use ref for variables comparison to avoid setState inside useMemo
125
+ const variablesRef = useRef(props.variables);
126
+ // Use effect to update the ref when props.variables changes
127
+ useEffect(() => {
128
+ if (!isEqual(props.variables, variablesRef.current)) {
129
+ variablesRef.current = props.variables;
130
+ setStableVariables(props.variables);
127
131
  }
132
+ }, [props.variables]);
133
+ const internalProps = useMemo(() => {
128
134
  return {
129
135
  ...props,
130
- variables: stableVariables.current,
136
+ variables: stableVariables,
131
137
  };
132
- }, [props]);
138
+ }, [props, stableVariables]);
133
139
  const [, { fetchMore, networkStatus }] = ApolloClient.useLazyQuery(document, {
134
140
  ...internalProps,
135
141
  context: {
@@ -156,7 +162,7 @@ const usePaginationQuery = (document, { ...props }) => {
156
162
  const onReset = useCallback(() => {
157
163
  setResetTrigger(prev => prev + 1);
158
164
  }, []);
159
- const { table: { setIsLoading, isLoading, setPageInfo, pageInfo, reset, nextPage, previousPage }, variables: { first, after }, } = useRelayPagination({
165
+ const { table: { setIsLoading, isLoading, setPageInfo, pageInfo, reset, nextPage, previousPage }, variables: { first, after, last, before }, } = useRelayPagination({
160
166
  pageSize: internalProps.pageSize || internalProps.variables?.first || defaultPageSize,
161
167
  onReset,
162
168
  });
@@ -168,7 +174,7 @@ const usePaginationQuery = (document, { ...props }) => {
168
174
  /**
169
175
  * To support pagination with page and pageSize, we need to convert the variables from first and after.
170
176
  */
171
- let fetchMoreVariables = {
177
+ const fetchMoreVariables = {
172
178
  ...internalProps.variables,
173
179
  ...(internalProps.variables && "page" in internalProps.variables && "pageSize" in internalProps.variables
174
180
  ? // eslint-disable-next-line local-rules/no-typescript-assertion
@@ -178,37 +184,25 @@ const usePaginationQuery = (document, { ...props }) => {
178
184
  }
179
185
  : { ...variables }),
180
186
  };
181
- // To support "pageable" queries we do it here! REMOVE once the serviceplans are updated to use the new pagination.
182
- fetchMoreVariables = {
183
- ...("pageable" in fetchMoreVariables
184
- ? {
185
- ...fetchMoreVariables,
186
- pageable: {
187
- first: fetchMoreVariables.first,
188
- last: fetchMoreVariables.last,
189
- before: fetchMoreVariables.before,
190
- after: fetchMoreVariables.after,
191
- pageSize: fetchMoreVariables.pageSize,
192
- },
193
- }
194
- : { ...fetchMoreVariables }),
195
- };
196
187
  fetchMore({
197
188
  variables: fetchMoreVariables,
198
- updateQuery: (_, { fetchMoreResult }) => {
189
+ updateQuery: (previousResult, { fetchMoreResult }) => {
199
190
  if (abortController.signal.aborted) {
200
191
  // if prev does not hold any data we don't want to return it,
201
192
  // since it will make the cache output an error to the console.
202
193
  // https://github.com/apollographql/apollo-client/issues/8677
203
194
  if (prev) {
204
- // eslint-disable-next-line local-rules/no-typescript-assertion
205
- return objectKeys(prev).length === 0 ? undefined : prev;
195
+ return objectKeys(prev).length === 0
196
+ ? undefined
197
+ : prev;
206
198
  }
207
199
  // eslint-disable-next-line local-rules/no-typescript-assertion
208
200
  return undefined;
209
201
  }
210
- setLastFetchedData(fetchMoreResult);
211
- const result = internalProps.updateQuery(prev, fetchMoreResult);
202
+ // Safely handle Apollo types
203
+ const typedResult = fetchMoreResult;
204
+ setLastFetchedData(typedResult);
205
+ const result = internalProps.updateQuery(prev, typedResult);
212
206
  setPageInfo(result.pageInfo || null);
213
207
  setData(result.data);
214
208
  setIsLoading(false);
@@ -233,15 +227,49 @@ const usePaginationQuery = (document, { ...props }) => {
233
227
  setData(undefined);
234
228
  reset();
235
229
  }, [internalProps.variables, reset]);
230
+ // Use a ref to track the current value of first variable
231
+ const lastRef = useRef(last);
232
+ useEffect(() => {
233
+ lastRef.current = last;
234
+ }, [last]);
235
+ const beforeRef = useRef(before);
236
236
  useEffect(() => {
237
- doFetchMore({ first, last: undefined, before: undefined, after: undefined }, undefined);
238
- // eslint-disable-next-line react-hooks/exhaustive-deps
237
+ beforeRef.current = before;
238
+ }, [before]);
239
+ const firstRef = useRef(first);
240
+ useEffect(() => {
241
+ firstRef.current = first;
242
+ }, [first]);
243
+ // Use a ref to track the current data
244
+ const dataRef = useRef(data);
245
+ useEffect(() => {
246
+ dataRef.current = data;
247
+ }, [data]);
248
+ // Store doFetchMore in a ref to avoid dependency cycles
249
+ const doFetchMoreRef = useRef(doFetchMore);
250
+ useEffect(() => {
251
+ doFetchMoreRef.current = doFetchMore;
252
+ }, [doFetchMore]);
253
+ // Stabilize the fetchMore call by using refs instead of direct dependencies
254
+ useEffect(() => {
255
+ const fetchVariables = {
256
+ first: firstRef.current,
257
+ last: undefined,
258
+ before: undefined,
259
+ after: undefined,
260
+ };
261
+ // Use the ref version to avoid dependency cycles
262
+ doFetchMoreRef.current(fetchVariables, undefined);
263
+ // Removed doFetchMore from dependencies to prevent refetch loops
239
264
  }, [internalProps.variables, resetTrigger]);
265
+ // Stabilize the pagination effect
240
266
  useEffect(() => {
241
267
  if (after) {
242
- doFetchMore({ first, after }, data);
268
+ const fetchVariables = { first: firstRef.current, after, last: lastRef.current, before: beforeRef.current };
269
+ // Use the ref version to avoid dependency cycles
270
+ doFetchMoreRef.current(fetchVariables, dataRef.current);
243
271
  }
244
- // eslint-disable-next-line react-hooks/exhaustive-deps
272
+ // Removed doFetchMore from dependencies to prevent refetch loops
245
273
  }, [after]);
246
274
  return useMemo(() => {
247
275
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-graphql-hooks",
3
- "version": "1.3.48",
3
+ "version": "1.3.52",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "engines": {
@@ -10,9 +10,9 @@
10
10
  "@apollo/client": "3.10.4",
11
11
  "react": "19.0.0",
12
12
  "lodash": "4.17.21",
13
- "@trackunit/i18n-library-translation": "1.3.47",
14
- "@trackunit/shared-utils": "1.5.43",
15
- "@trackunit/react-table-pagination": "1.3.44"
13
+ "@trackunit/i18n-library-translation": "1.3.50",
14
+ "@trackunit/shared-utils": "1.5.46",
15
+ "@trackunit/react-table-pagination": "1.3.47"
16
16
  },
17
17
  "module": "./index.esm.js",
18
18
  "main": "./index.cjs.js",