@graphcommerce/react-hook-form 8.1.0-canary.9 → 9.0.0-canary.101
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.
- package/CHANGELOG.md +223 -26
- package/index.ts +6 -4
- package/package.json +10 -5
- package/src/ComposedForm/ComposedSubmit.tsx +2 -0
- package/src/ComposedForm/types.ts +1 -1
- package/src/useFormAutoSubmit.tsx +37 -11
- package/src/useFormGql.tsx +109 -19
- package/src/useFormGqlMutation.tsx +1 -1
- package/src/useFormGqlQuery.tsx +1 -1
- package/src/useFormPersist.tsx +4 -1
- package/src/utils/debounce.ts +16 -0
- package/src/utils/tryTuple.ts +25 -0
- package/src/utils/useDebounce.ts +59 -0
- package/src/utils/useDebounceCallback.ts +8 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,215 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 9.0.0-canary.101
|
|
4
|
+
|
|
5
|
+
## 9.0.0-canary.100
|
|
6
|
+
|
|
7
|
+
## 9.0.0-canary.99
|
|
8
|
+
|
|
9
|
+
## 9.0.0-canary.98
|
|
10
|
+
|
|
11
|
+
## 9.0.0-canary.97
|
|
12
|
+
|
|
13
|
+
## 9.0.0-canary.96
|
|
14
|
+
|
|
15
|
+
## 9.0.0-canary.95
|
|
16
|
+
|
|
17
|
+
## 9.0.0-canary.94
|
|
18
|
+
|
|
19
|
+
## 9.0.0-canary.93
|
|
20
|
+
|
|
21
|
+
## 9.0.0-canary.92
|
|
22
|
+
|
|
23
|
+
## 9.0.0-canary.91
|
|
24
|
+
|
|
25
|
+
## 9.0.0-canary.90
|
|
26
|
+
|
|
27
|
+
### Minor Changes
|
|
28
|
+
|
|
29
|
+
- [#2391](https://github.com/graphcommerce-org/graphcommerce/pull/2391) [`c1fa10f`](https://github.com/graphcommerce-org/graphcommerce/commit/c1fa10f995f562741b7574d465580e5405982a70) - Prevent overwriting custom context in useFormGqlMutation by merging operationOptions before execution. ([@wimvdputten](https://github.com/wimvdputten))
|
|
30
|
+
|
|
31
|
+
## 9.0.0-canary.89
|
|
32
|
+
|
|
33
|
+
## 9.0.0-canary.88
|
|
34
|
+
|
|
35
|
+
## 9.0.0-canary.87
|
|
36
|
+
|
|
37
|
+
## 9.0.0-canary.86
|
|
38
|
+
|
|
39
|
+
## 9.0.0-canary.85
|
|
40
|
+
|
|
41
|
+
## 9.0.0-canary.84
|
|
42
|
+
|
|
43
|
+
## 9.0.0-canary.83
|
|
44
|
+
|
|
45
|
+
## 9.0.0-canary.82
|
|
46
|
+
|
|
47
|
+
## 9.0.0-canary.81
|
|
48
|
+
|
|
49
|
+
## 9.0.0-canary.80
|
|
50
|
+
|
|
51
|
+
### Minor Changes
|
|
52
|
+
|
|
53
|
+
- [#2341](https://github.com/graphcommerce-org/graphcommerce/pull/2341) [`16e2980`](https://github.com/graphcommerce-org/graphcommerce/commit/16e2980da4b72330642e59e8c82d1acde387e4fc) - useFormGql and it's derived hooks now have a new `skipUnchanged` prop. The form will only be submitted when there are fields dirty in a form. This reduces the amount of queries ran in the checkout greatly. ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
|
|
54
|
+
|
|
55
|
+
- [#2341](https://github.com/graphcommerce-org/graphcommerce/pull/2341) [`1d6512d`](https://github.com/graphcommerce-org/graphcommerce/commit/1d6512d4118cfb46602aa1f2432c3566fdb3261d) - Rename experimental_useV2 prop to deprecated_useV1 in useFromGql and enable it by default ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
|
|
56
|
+
|
|
57
|
+
### Patch Changes
|
|
58
|
+
|
|
59
|
+
- [#2341](https://github.com/graphcommerce-org/graphcommerce/pull/2341) [`af45239`](https://github.com/graphcommerce-org/graphcommerce/commit/af452399eaab59ee4e13484fdc9cb0a7660da531) - When a useFormGql throws an error in the onBeforeSubmit method or onComplete method it will setError('root.thrown') with the message, allowing it to be displayed somewhere. PaymentMethodButton will now render this as an ErrorSnackbar. ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
|
|
60
|
+
|
|
61
|
+
## 9.0.0-canary.79
|
|
62
|
+
|
|
63
|
+
## 9.0.0-canary.78
|
|
64
|
+
|
|
65
|
+
## 9.0.0-canary.77
|
|
66
|
+
|
|
67
|
+
## 9.0.0-canary.76
|
|
68
|
+
|
|
69
|
+
## 9.0.0-canary.75
|
|
70
|
+
|
|
71
|
+
## 9.0.0-canary.74
|
|
72
|
+
|
|
73
|
+
## 9.0.0-canary.73
|
|
74
|
+
|
|
75
|
+
## 9.0.0-canary.72
|
|
76
|
+
|
|
77
|
+
## 9.0.0-canary.71
|
|
78
|
+
|
|
79
|
+
## 9.0.0-canary.70
|
|
80
|
+
|
|
81
|
+
## 9.0.0-canary.69
|
|
82
|
+
|
|
83
|
+
## 9.0.0-canary.68
|
|
84
|
+
|
|
85
|
+
## 9.0.0-canary.67
|
|
86
|
+
|
|
87
|
+
## 9.0.0-canary.66
|
|
88
|
+
|
|
89
|
+
## 9.0.0-canary.65
|
|
90
|
+
|
|
91
|
+
## 9.0.0-canary.64
|
|
92
|
+
|
|
93
|
+
## 9.0.0-canary.63
|
|
94
|
+
|
|
95
|
+
## 9.0.0-canary.62
|
|
96
|
+
|
|
97
|
+
## 9.0.0-canary.61
|
|
98
|
+
|
|
99
|
+
## 9.0.0-canary.60
|
|
100
|
+
|
|
101
|
+
## 9.0.0-canary.59
|
|
102
|
+
|
|
103
|
+
## 9.0.0-canary.58
|
|
104
|
+
|
|
105
|
+
## 9.0.0-canary.57
|
|
106
|
+
|
|
107
|
+
## 9.0.0-canary.56
|
|
108
|
+
|
|
109
|
+
## 9.0.0-canary.55
|
|
110
|
+
|
|
111
|
+
## 9.0.0-canary.54
|
|
112
|
+
|
|
113
|
+
## 8.1.0-canary.53
|
|
114
|
+
|
|
115
|
+
### Minor Changes
|
|
116
|
+
|
|
117
|
+
- [#2325](https://github.com/graphcommerce-org/graphcommerce/pull/2325) [`058fb17`](https://github.com/graphcommerce-org/graphcommerce/commit/058fb1777bdaa51ded6d37529e59a3cc5f0eac06) - Solve an issue where onBeforeSubmit and onComplete would become an 'stale closure' where variables inside wouldn't be updated. By wrapping onBeforeSubmit and onComplete in useEventCallback these functions are updated when outside values get changed. ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
|
|
118
|
+
|
|
119
|
+
## 8.1.0-canary.52
|
|
120
|
+
|
|
121
|
+
## 8.1.0-canary.51
|
|
122
|
+
|
|
123
|
+
## 8.1.0-canary.50
|
|
124
|
+
|
|
125
|
+
## 8.1.0-canary.49
|
|
126
|
+
|
|
127
|
+
## 8.1.0-canary.48
|
|
128
|
+
|
|
129
|
+
## 8.1.0-canary.47
|
|
130
|
+
|
|
131
|
+
## 8.1.0-canary.46
|
|
132
|
+
|
|
133
|
+
### Patch Changes
|
|
134
|
+
|
|
135
|
+
- [#2314](https://github.com/graphcommerce-org/graphcommerce/pull/2314) [`490bbfb`](https://github.com/graphcommerce-org/graphcommerce/commit/490bbfb5d88a7f58e83fa9c8b7f475c277a0eda3) - Added missing dependencies of lodash and @types/lodash ([@paales](https://github.com/paales))
|
|
136
|
+
|
|
137
|
+
## 8.1.0-canary.45
|
|
138
|
+
|
|
139
|
+
## 8.1.0-canary.44
|
|
140
|
+
|
|
141
|
+
## 8.1.0-canary.43
|
|
142
|
+
|
|
143
|
+
## 8.1.0-canary.42
|
|
144
|
+
|
|
145
|
+
## 8.1.0-canary.41
|
|
146
|
+
|
|
147
|
+
## 8.1.0-canary.40
|
|
148
|
+
|
|
149
|
+
## 8.1.0-canary.39
|
|
150
|
+
|
|
151
|
+
## 8.1.0-canary.38
|
|
152
|
+
|
|
153
|
+
### Patch Changes
|
|
154
|
+
|
|
155
|
+
- [#2305](https://github.com/graphcommerce-org/graphcommerce/pull/2305) [`77e8297`](https://github.com/graphcommerce-org/graphcommerce/commit/77e82976816994336c616208a651cb18ce9ea270) - Fix bug with persist not applying saved changes by moving <FromPersist/> below the form components ([@Giovanni-Schroevers](https://github.com/Giovanni-Schroevers))
|
|
156
|
+
|
|
157
|
+
## 8.1.0-canary.37
|
|
158
|
+
|
|
159
|
+
## 8.1.0-canary.36
|
|
160
|
+
|
|
161
|
+
## 8.1.0-canary.35
|
|
162
|
+
|
|
163
|
+
## 8.1.0-canary.34
|
|
164
|
+
|
|
165
|
+
## 8.1.0-canary.33
|
|
166
|
+
|
|
167
|
+
## 8.1.0-canary.32
|
|
168
|
+
|
|
169
|
+
## 8.1.0-canary.31
|
|
170
|
+
|
|
171
|
+
## 8.1.0-canary.30
|
|
172
|
+
|
|
173
|
+
## 8.1.0-canary.29
|
|
174
|
+
|
|
175
|
+
## 8.1.0-canary.28
|
|
176
|
+
|
|
177
|
+
## 8.1.0-canary.27
|
|
178
|
+
|
|
179
|
+
## 8.1.0-canary.26
|
|
180
|
+
|
|
181
|
+
## 8.1.0-canary.25
|
|
182
|
+
|
|
183
|
+
## 8.1.0-canary.24
|
|
184
|
+
|
|
185
|
+
## 8.1.0-canary.23
|
|
186
|
+
|
|
187
|
+
## 8.1.0-canary.22
|
|
188
|
+
|
|
189
|
+
## 8.1.0-canary.21
|
|
190
|
+
|
|
191
|
+
## 8.1.0-canary.20
|
|
192
|
+
|
|
193
|
+
## 8.1.0-canary.19
|
|
194
|
+
|
|
195
|
+
## 8.1.0-canary.18
|
|
196
|
+
|
|
197
|
+
## 8.1.0-canary.17
|
|
198
|
+
|
|
199
|
+
## 8.1.0-canary.16
|
|
200
|
+
|
|
201
|
+
## 8.1.0-canary.15
|
|
202
|
+
|
|
203
|
+
## 8.1.0-canary.14
|
|
204
|
+
|
|
205
|
+
## 8.1.0-canary.13
|
|
206
|
+
|
|
207
|
+
## 8.1.0-canary.12
|
|
208
|
+
|
|
209
|
+
## 8.1.0-canary.11
|
|
210
|
+
|
|
211
|
+
## 8.1.0-canary.10
|
|
212
|
+
|
|
3
213
|
## 8.1.0-canary.9
|
|
4
214
|
|
|
5
215
|
## 8.1.0-canary.8
|
|
@@ -18,20 +228,15 @@
|
|
|
18
228
|
|
|
19
229
|
### Patch Changes
|
|
20
230
|
|
|
21
|
-
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`43bd04a`](https://github.com/graphcommerce-org/graphcommerce/commit/43bd04a777c5800cc7e01bee1e123a5aad82f194) - Add deprecation warnings for useFormMuiRegister. Refactor useFormPersist to useWatch and add a separate `<FormPersist/>` component to prevent rerenders.
|
|
22
|
-
([@FrankHarland](https://github.com/FrankHarland))
|
|
231
|
+
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`43bd04a`](https://github.com/graphcommerce-org/graphcommerce/commit/43bd04a777c5800cc7e01bee1e123a5aad82f194) - Add deprecation warnings for useFormMuiRegister. Refactor useFormPersist to useWatch and add a separate `<FormPersist/>` component to prevent rerenders. ([@FrankHarland](https://github.com/FrankHarland))
|
|
23
232
|
|
|
24
|
-
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`0767bc4`](https://github.com/graphcommerce-org/graphcommerce/commit/0767bc40f7b596209f24ca4e745ff0441f3275c9) - Upgrade input components to no longer use muiRegister, which improves INP scores
|
|
25
|
-
([@FrankHarland](https://github.com/FrankHarland))
|
|
233
|
+
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`0767bc4`](https://github.com/graphcommerce-org/graphcommerce/commit/0767bc40f7b596209f24ca4e745ff0441f3275c9) - Upgrade input components to no longer use muiRegister, which improves INP scores ([@FrankHarland](https://github.com/FrankHarland))
|
|
26
234
|
|
|
27
|
-
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`02da217`](https://github.com/graphcommerce-org/graphcommerce/commit/02da2172ef702133510f6923190efae2801032c5) - Migrate most usages of useFormAutoSubmit to <FormAutoSubmit/> and deprecated useFormAutoSubmit
|
|
28
|
-
([@FrankHarland](https://github.com/FrankHarland))
|
|
235
|
+
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`02da217`](https://github.com/graphcommerce-org/graphcommerce/commit/02da2172ef702133510f6923190efae2801032c5) - Migrate most usages of useFormAutoSubmit to <FormAutoSubmit/> and deprecated useFormAutoSubmit ([@FrankHarland](https://github.com/FrankHarland))
|
|
29
236
|
|
|
30
|
-
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`530076e`](https://github.com/graphcommerce-org/graphcommerce/commit/530076e3664703cb8b577b7fcf1998a420819f60) - Moved all usages of useFormPersist to the <FormPersist/> component to prevent rerenders.
|
|
31
|
-
([@FrankHarland](https://github.com/FrankHarland))
|
|
237
|
+
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`530076e`](https://github.com/graphcommerce-org/graphcommerce/commit/530076e3664703cb8b577b7fcf1998a420819f60) - Moved all usages of useFormPersist to the <FormPersist/> component to prevent rerenders. ([@FrankHarland](https://github.com/FrankHarland))
|
|
32
238
|
|
|
33
|
-
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`1a6d0c4`](https://github.com/graphcommerce-org/graphcommerce/commit/1a6d0c4a3584b1e404b444f1ca44c68eaad56cb7) - Mark useFormValidFields as deprecated: Please use TextInputElement, SelectElement, etc. with the showValid prop
|
|
34
|
-
([@FrankHarland](https://github.com/FrankHarland))
|
|
239
|
+
- [#2234](https://github.com/graphcommerce-org/graphcommerce/pull/2234) [`1a6d0c4`](https://github.com/graphcommerce-org/graphcommerce/commit/1a6d0c4a3584b1e404b444f1ca44c68eaad56cb7) - Mark useFormValidFields as deprecated: Please use TextInputElement, SelectElement, etc. with the showValid prop ([@FrankHarland](https://github.com/FrankHarland))
|
|
35
240
|
|
|
36
241
|
## 8.0.6-canary.1
|
|
37
242
|
|
|
@@ -41,8 +246,7 @@
|
|
|
41
246
|
|
|
42
247
|
### Patch Changes
|
|
43
248
|
|
|
44
|
-
- [#2237](https://github.com/graphcommerce-org/graphcommerce/pull/2237) [`60f387d`](https://github.com/graphcommerce-org/graphcommerce/commit/60f387d4a037736aa8105fa45728ee481bdaf887) - Solve an issue where the checkout address form wouldn't be automatically submitted on change.
|
|
45
|
-
([@bramvanderholst](https://github.com/bramvanderholst))
|
|
249
|
+
- [#2237](https://github.com/graphcommerce-org/graphcommerce/pull/2237) [`60f387d`](https://github.com/graphcommerce-org/graphcommerce/commit/60f387d4a037736aa8105fa45728ee481bdaf887) - Solve an issue where the checkout address form wouldn't be automatically submitted on change. ([@bramvanderholst](https://github.com/bramvanderholst))
|
|
46
250
|
|
|
47
251
|
## 8.0.5-canary.10
|
|
48
252
|
|
|
@@ -60,8 +264,7 @@
|
|
|
60
264
|
|
|
61
265
|
### Patch Changes
|
|
62
266
|
|
|
63
|
-
- [#2237](https://github.com/graphcommerce-org/graphcommerce/pull/2237) [`60f387d`](https://github.com/graphcommerce-org/graphcommerce/commit/60f387d4a037736aa8105fa45728ee481bdaf887) - Solve an issue where the checkout address form wouldn't be automatically submitted on change.
|
|
64
|
-
([@bramvanderholst](https://github.com/bramvanderholst))
|
|
267
|
+
- [#2237](https://github.com/graphcommerce-org/graphcommerce/pull/2237) [`60f387d`](https://github.com/graphcommerce-org/graphcommerce/commit/60f387d4a037736aa8105fa45728ee481bdaf887) - Solve an issue where the checkout address form wouldn't be automatically submitted on change. ([@bramvanderholst](https://github.com/bramvanderholst))
|
|
65
268
|
|
|
66
269
|
## 8.0.5-canary.3
|
|
67
270
|
|
|
@@ -81,11 +284,9 @@
|
|
|
81
284
|
|
|
82
285
|
### Patch Changes
|
|
83
286
|
|
|
84
|
-
- [#2206](https://github.com/graphcommerce-org/graphcommerce/pull/2206) [`855ab09`](https://github.com/graphcommerce-org/graphcommerce/commit/855ab097b9ea204a7c73c6550b7a5e9e2290f378) - Cleanup `<FormAutoSubmit/>` and remove internal hook.
|
|
85
|
-
([@paales](https://github.com/paales))
|
|
287
|
+
- [#2206](https://github.com/graphcommerce-org/graphcommerce/pull/2206) [`855ab09`](https://github.com/graphcommerce-org/graphcommerce/commit/855ab097b9ea204a7c73c6550b7a5e9e2290f378) - Cleanup `<FormAutoSubmit/>` and remove internal hook. ([@paales](https://github.com/paales))
|
|
86
288
|
|
|
87
|
-
- [#2212](https://github.com/graphcommerce-org/graphcommerce/pull/2212) [`7c9f5da`](https://github.com/graphcommerce-org/graphcommerce/commit/7c9f5da1d458a19b0316c556c75415ff28bc5b2d) - Added noValidate prop so we can use the FormAutoSubmit component to submit partial forms
|
|
88
|
-
([@paales](https://github.com/paales))
|
|
289
|
+
- [#2212](https://github.com/graphcommerce-org/graphcommerce/pull/2212) [`7c9f5da`](https://github.com/graphcommerce-org/graphcommerce/commit/7c9f5da1d458a19b0316c556c75415ff28bc5b2d) - Added noValidate prop so we can use the FormAutoSubmit component to submit partial forms ([@paales](https://github.com/paales))
|
|
89
290
|
|
|
90
291
|
## 8.0.3-canary.6
|
|
91
292
|
|
|
@@ -93,8 +294,7 @@
|
|
|
93
294
|
|
|
94
295
|
### Patch Changes
|
|
95
296
|
|
|
96
|
-
- [#2212](https://github.com/graphcommerce-org/graphcommerce/pull/2212) [`7c9f5da`](https://github.com/graphcommerce-org/graphcommerce/commit/7c9f5da1d458a19b0316c556c75415ff28bc5b2d) - Added noValidate prop so we can use the FormAutoSubmit component to submit partial forms
|
|
97
|
-
([@paales](https://github.com/paales))
|
|
297
|
+
- [#2212](https://github.com/graphcommerce-org/graphcommerce/pull/2212) [`7c9f5da`](https://github.com/graphcommerce-org/graphcommerce/commit/7c9f5da1d458a19b0316c556c75415ff28bc5b2d) - Added noValidate prop so we can use the FormAutoSubmit component to submit partial forms ([@paales](https://github.com/paales))
|
|
98
298
|
|
|
99
299
|
## 8.0.3-canary.4
|
|
100
300
|
|
|
@@ -102,8 +302,7 @@
|
|
|
102
302
|
|
|
103
303
|
### Patch Changes
|
|
104
304
|
|
|
105
|
-
- [#2206](https://github.com/graphcommerce-org/graphcommerce/pull/2206) [`855ab09`](https://github.com/graphcommerce-org/graphcommerce/commit/855ab097b9ea204a7c73c6550b7a5e9e2290f378) - Cleanup `<FormAutoSubmit/>` and remove internal hook.
|
|
106
|
-
([@paales](https://github.com/paales))
|
|
305
|
+
- [#2206](https://github.com/graphcommerce-org/graphcommerce/pull/2206) [`855ab09`](https://github.com/graphcommerce-org/graphcommerce/commit/855ab097b9ea204a7c73c6550b7a5e9e2290f378) - Cleanup `<FormAutoSubmit/>` and remove internal hook. ([@paales](https://github.com/paales))
|
|
107
306
|
|
|
108
307
|
## 8.0.3-canary.2
|
|
109
308
|
|
|
@@ -137,11 +336,9 @@
|
|
|
137
336
|
|
|
138
337
|
### Patch Changes
|
|
139
338
|
|
|
140
|
-
- [#2093](https://github.com/graphcommerce-org/graphcommerce/pull/2093) [`112b041`](https://github.com/graphcommerce-org/graphcommerce/commit/112b041f01a33fbd521ce3eb3955844f96b29917) - Created a new experimental mutation abort feature inside `useFormGql`. This will allow redundant mutations to be canceled. This is enabled when the `experimental_useV2` prop on the `useFormGql` hook is used.
|
|
141
|
-
([@mikekeehnen](https://github.com/mikekeehnen))
|
|
339
|
+
- [#2093](https://github.com/graphcommerce-org/graphcommerce/pull/2093) [`112b041`](https://github.com/graphcommerce-org/graphcommerce/commit/112b041f01a33fbd521ce3eb3955844f96b29917) - Created a new experimental mutation abort feature inside `useFormGql`. This will allow redundant mutations to be canceled. This is enabled when the `experimental_useV2` prop on the `useFormGql` hook is used. ([@mikekeehnen](https://github.com/mikekeehnen))
|
|
142
340
|
|
|
143
|
-
- [#2007](https://github.com/graphcommerce-org/graphcommerce/pull/2007) [`f59c276`](https://github.com/graphcommerce-org/graphcommerce/commit/f59c276605f9ed649d1197a9ba0e3f12d7c6d026) - Crosssell behavior now properly shows for the latest added product. Added latest submitted variables to be retrieved when using the useFormGql hook.
|
|
144
|
-
([@JoshuaS98](https://github.com/JoshuaS98))
|
|
341
|
+
- [#2007](https://github.com/graphcommerce-org/graphcommerce/pull/2007) [`f59c276`](https://github.com/graphcommerce-org/graphcommerce/commit/f59c276605f9ed649d1197a9ba0e3f12d7c6d026) - Crosssell behavior now properly shows for the latest added product. Added latest submitted variables to be retrieved when using the useFormGql hook. ([@JoshuaS98](https://github.com/JoshuaS98))
|
|
145
342
|
|
|
146
343
|
## 8.0.0-canary.100
|
|
147
344
|
|
package/index.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export * from 'react-hook-form'
|
|
2
|
+
export * from './src/ComposedForm'
|
|
3
|
+
export * from './src/useFormAutoSubmit'
|
|
4
|
+
export * from './src/useFormGql'
|
|
2
5
|
export * from './src/useFormGqlMutation'
|
|
3
6
|
export * from './src/useFormGqlQuery'
|
|
4
|
-
export * from './src/useFormAutoSubmit'
|
|
5
|
-
export * from './src/useFormPersist'
|
|
6
7
|
export * from './src/useFormMuiRegister'
|
|
8
|
+
export * from './src/useFormPersist'
|
|
7
9
|
export * from './src/useFormValidFields'
|
|
8
|
-
export * from './src/
|
|
10
|
+
export * from './src/utils/tryTuple'
|
|
11
|
+
export * from './src/utils/useDebounce'
|
|
9
12
|
export * from './src/validationPatterns'
|
|
10
|
-
export * from './src/ComposedForm'
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@graphcommerce/react-hook-form",
|
|
3
3
|
"homepage": "https://www.graphcommerce.org/",
|
|
4
4
|
"repository": "github:graphcommerce-org/graphcommerce",
|
|
5
|
-
"version": "
|
|
5
|
+
"version": "9.0.0-canary.101",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -12,16 +12,21 @@
|
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
14
|
"devDependencies": {
|
|
15
|
-
"@testing-library/react": "^14.1
|
|
15
|
+
"@testing-library/react": "^14.3.1"
|
|
16
16
|
},
|
|
17
17
|
"peerDependencies": {
|
|
18
18
|
"@apollo/client": "^3",
|
|
19
|
-
"@graphcommerce/eslint-config-pwa": "^
|
|
20
|
-
"@graphcommerce/prettier-config-pwa": "^
|
|
21
|
-
"@graphcommerce/typescript-config-pwa": "^
|
|
19
|
+
"@graphcommerce/eslint-config-pwa": "^9.0.0-canary.101",
|
|
20
|
+
"@graphcommerce/prettier-config-pwa": "^9.0.0-canary.101",
|
|
21
|
+
"@graphcommerce/typescript-config-pwa": "^9.0.0-canary.101",
|
|
22
|
+
"@mui/utils": "^5",
|
|
22
23
|
"graphql": "^16.6.0",
|
|
23
24
|
"react": "^18.2.0",
|
|
24
25
|
"react-dom": "^18.2.0",
|
|
25
26
|
"react-hook-form": "^7"
|
|
27
|
+
},
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@types/lodash": "^4.17.10",
|
|
30
|
+
"lodash": "^4.17.21"
|
|
26
31
|
}
|
|
27
32
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ApolloError } from '@apollo/client'
|
|
2
2
|
import React, { useContext, useEffect, useRef } from 'react'
|
|
3
|
+
import { GlobalError } from 'react-hook-form'
|
|
3
4
|
import { isFormGqlOperation } from '../useFormGqlMutation'
|
|
4
5
|
import { composedFormContext } from './context'
|
|
5
6
|
import { ComposedSubmitRenderComponentProps } from './types'
|
|
@@ -119,6 +120,7 @@ export function ComposedSubmit(props: ComposedSubmitProps) {
|
|
|
119
120
|
}
|
|
120
121
|
|
|
121
122
|
const errors: ApolloError[] = []
|
|
123
|
+
|
|
122
124
|
formEntries.forEach(([, { form }]) => {
|
|
123
125
|
if (form && isFormGqlOperation(form) && form.error) errors.push(form.error)
|
|
124
126
|
})
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ApolloError } from '@apollo/client'
|
|
2
|
-
import type { FieldValues, FormState, UseFormReturn } from 'react-hook-form'
|
|
2
|
+
import type { FieldValues, FormState, GlobalError, UseFormReturn } from 'react-hook-form'
|
|
3
3
|
import type { SetOptional } from 'type-fest'
|
|
4
4
|
|
|
5
5
|
export type UseFormComposeOptions<V extends FieldValues = FieldValues> = {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
/* eslint-disable react/no-unused-prop-types */
|
|
1
2
|
import { cloneDeep } from '@apollo/client/utilities'
|
|
2
3
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
3
4
|
import { useMemoObject } from '@graphcommerce/next-ui/hooks/useMemoObject'
|
|
@@ -13,8 +14,7 @@ import {
|
|
|
13
14
|
useFormState,
|
|
14
15
|
useWatch,
|
|
15
16
|
} from 'react-hook-form'
|
|
16
|
-
import {
|
|
17
|
-
import { useDebouncedCallback } from './utils/useDebounceCallback'
|
|
17
|
+
import { DebounceSettings, useDebounce } from './utils/useDebounce'
|
|
18
18
|
|
|
19
19
|
export type UseFormAutoSubmitOptions<TForm extends UseFormReturn<V>, V extends FieldValues> = {
|
|
20
20
|
/** Instance of current form */
|
|
@@ -116,23 +116,40 @@ export type FormAutoSubmitProps<TFieldValues extends FieldValues = FieldValues>
|
|
|
116
116
|
parallel?: boolean
|
|
117
117
|
|
|
118
118
|
noValidate?: boolean
|
|
119
|
-
} & DebounceOptions &
|
|
120
|
-
Omit<UseWatchProps<TFieldValues>, 'defaultValue'>
|
|
121
119
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
120
|
+
wait?: number
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Only 0 does anthing and will submit immediately. Any other value will be ignored.
|
|
124
|
+
*
|
|
125
|
+
* @deprecated Please use leading instead
|
|
126
|
+
*/
|
|
127
|
+
initialWait?: number
|
|
128
|
+
} & Omit<UseWatchProps<TFieldValues>, 'defaultValue'> &
|
|
129
|
+
DebounceSettings
|
|
130
|
+
|
|
131
|
+
export function useAutoSubmitBase<TFieldValues extends FieldValues = FieldValues>(
|
|
126
132
|
props: FormAutoSubmitProps<TFieldValues>,
|
|
127
133
|
) {
|
|
128
|
-
const {
|
|
134
|
+
const {
|
|
135
|
+
wait = 166,
|
|
136
|
+
initialWait,
|
|
137
|
+
maxWait,
|
|
138
|
+
leading,
|
|
139
|
+
trailing,
|
|
140
|
+
|
|
141
|
+
submit,
|
|
142
|
+
parallel,
|
|
143
|
+
noValidate,
|
|
144
|
+
...watchOptions
|
|
145
|
+
} = props
|
|
129
146
|
|
|
130
147
|
// We create a stable object from the values, so that we can compare them later
|
|
131
148
|
const values = useMemoObject(cloneDeep(useWatch(watchOptions)))
|
|
132
149
|
const oldValues = useRef<DeepPartialSkipArrayKey<TFieldValues>>(values)
|
|
133
150
|
const { isValidating, isSubmitting, isValid } = useFormState(watchOptions)
|
|
134
151
|
|
|
135
|
-
const submitDebounced =
|
|
152
|
+
const submitDebounced = useDebounce(
|
|
136
153
|
async () => {
|
|
137
154
|
try {
|
|
138
155
|
oldValues.current = values
|
|
@@ -141,7 +158,8 @@ function FormAutoSubmitBase<TFieldValues extends FieldValues = FieldValues>(
|
|
|
141
158
|
// We're not interested if the submission actually succeeds, that should be handled by the form itself.
|
|
142
159
|
}
|
|
143
160
|
},
|
|
144
|
-
|
|
161
|
+
wait,
|
|
162
|
+
{ leading: leading ?? initialWait === 0, maxWait, trailing },
|
|
145
163
|
)
|
|
146
164
|
|
|
147
165
|
const valid = (noValidate ? true : isValid) && !isValidating
|
|
@@ -152,7 +170,15 @@ function FormAutoSubmitBase<TFieldValues extends FieldValues = FieldValues>(
|
|
|
152
170
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
153
171
|
submitDebounced()
|
|
154
172
|
}
|
|
173
|
+
}
|
|
155
174
|
|
|
175
|
+
/**
|
|
176
|
+
* This is made a components so the useWatch that is used here doesn't retrigger the rerender of the parent component.
|
|
177
|
+
*/
|
|
178
|
+
function FormAutoSubmitBase<TFieldValues extends FieldValues = FieldValues>(
|
|
179
|
+
props: FormAutoSubmitProps<TFieldValues>,
|
|
180
|
+
) {
|
|
181
|
+
useAutoSubmitBase(props)
|
|
156
182
|
return null
|
|
157
183
|
}
|
|
158
184
|
|
package/src/useFormGql.tsx
CHANGED
|
@@ -1,26 +1,42 @@
|
|
|
1
1
|
import {
|
|
2
|
-
FetchResult,
|
|
3
|
-
TypedDocumentNode,
|
|
4
|
-
MutationTuple,
|
|
5
2
|
ApolloError,
|
|
3
|
+
FetchResult,
|
|
6
4
|
LazyQueryResultTuple,
|
|
5
|
+
MutationTuple,
|
|
6
|
+
TypedDocumentNode,
|
|
7
|
+
isApolloError,
|
|
8
|
+
MutationHookOptions,
|
|
9
|
+
LazyQueryHookOptions,
|
|
7
10
|
} from '@apollo/client'
|
|
11
|
+
import { getOperationName } from '@apollo/client/utilities'
|
|
12
|
+
import useEventCallback from '@mui/utils/useEventCallback'
|
|
8
13
|
import { useEffect, useRef } from 'react'
|
|
9
14
|
import { DefaultValues, FieldValues, UseFormProps, UseFormReturn } from 'react-hook-form'
|
|
10
15
|
import diff from './diff'
|
|
11
16
|
import { useGqlDocumentHandler, UseGqlDocumentHandler } from './useGqlDocumentHandler'
|
|
17
|
+
import { tryAsync } from './utils/tryTuple'
|
|
12
18
|
|
|
13
19
|
export type OnCompleteFn<Q, V> = (data: FetchResult<Q>, variables: V) => void | Promise<void>
|
|
14
20
|
|
|
15
21
|
type UseFormGraphQLCallbacks<Q, V> = {
|
|
16
22
|
/**
|
|
17
23
|
* Allows you to modify the variablels computed by the form to make it compatible with the GraphQL
|
|
18
|
-
* Mutation.
|
|
24
|
+
* Mutation.
|
|
25
|
+
*
|
|
26
|
+
* When returning false, it will silently stop the submission.
|
|
27
|
+
* When an error is thrown, it will be set as an ApolloError
|
|
19
28
|
*/
|
|
20
29
|
onBeforeSubmit?: (variables: V) => V | false | Promise<V | false>
|
|
30
|
+
/**
|
|
31
|
+
* Called after the mutation has been executed. Allows you to handle the result of the mutation.
|
|
32
|
+
*
|
|
33
|
+
* When an error is thrown, it will be set as an ApolloError
|
|
34
|
+
*/
|
|
21
35
|
onComplete?: OnCompleteFn<Q, V>
|
|
22
36
|
|
|
23
37
|
/**
|
|
38
|
+
* @deprecated Not used anymore, is now the default
|
|
39
|
+
*
|
|
24
40
|
* Changes:
|
|
25
41
|
* - Restores `defaultValues` functionality to original functionality, use `values` instead.
|
|
26
42
|
* - Does not reset the form after submission, use `values` instead.
|
|
@@ -43,6 +59,19 @@ type UseFormGraphQLCallbacks<Q, V> = {
|
|
|
43
59
|
* ```
|
|
44
60
|
*/
|
|
45
61
|
experimental_useV2?: boolean
|
|
62
|
+
/**
|
|
63
|
+
* To restore the previous functionality of the useFormGqlMutation, set this to true.
|
|
64
|
+
*
|
|
65
|
+
* @deprecated Will be removed in the next version.
|
|
66
|
+
*/
|
|
67
|
+
deprecated_useV1?: boolean
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Only submit the form when there are dirty fields. If all fields are clean, we skip the submission.
|
|
71
|
+
*
|
|
72
|
+
* Form is still set to isSubmitted and isSubmitSuccessful.
|
|
73
|
+
*/
|
|
74
|
+
skipUnchanged?: boolean
|
|
46
75
|
}
|
|
47
76
|
|
|
48
77
|
export type UseFormGraphQlOptions<Q, V extends FieldValues> = UseFormProps<V> &
|
|
@@ -71,7 +100,11 @@ export function useFormGql<Q, V extends FieldValues>(
|
|
|
71
100
|
document: TypedDocumentNode<Q, V>
|
|
72
101
|
form: UseFormReturn<V>
|
|
73
102
|
tuple: MutationTuple<Q, V> | LazyQueryResultTuple<Q, V>
|
|
103
|
+
operationOptions?:
|
|
104
|
+
| Omit<MutationHookOptions<Q, V>, 'fetchPolicy' | 'variables'>
|
|
105
|
+
| Omit<LazyQueryHookOptions<Q, V>, 'fetchPolicy' | 'variables'>
|
|
74
106
|
defaultValues?: UseFormProps<V>['defaultValues']
|
|
107
|
+
skipUnchanged?: boolean
|
|
75
108
|
} & UseFormGraphQLCallbacks<Q, V>,
|
|
76
109
|
): UseFormGqlMethods<Q, V> {
|
|
77
110
|
const {
|
|
@@ -80,20 +113,23 @@ export function useFormGql<Q, V extends FieldValues>(
|
|
|
80
113
|
document,
|
|
81
114
|
form,
|
|
82
115
|
tuple,
|
|
116
|
+
operationOptions,
|
|
117
|
+
skipUnchanged,
|
|
83
118
|
defaultValues,
|
|
84
|
-
|
|
119
|
+
deprecated_useV1 = false,
|
|
85
120
|
} = options
|
|
86
121
|
const { encode, type, ...gqlDocumentHandler } = useGqlDocumentHandler<Q, V>(document)
|
|
87
122
|
const [execute, { data, error, loading }] = tuple
|
|
88
123
|
|
|
89
124
|
const submittedVariables = useRef<V>()
|
|
125
|
+
const returnedError = useRef<ApolloError>()
|
|
90
126
|
|
|
91
127
|
// automatically updates the default values
|
|
92
128
|
const initital = useRef(true)
|
|
93
129
|
const controllerRef = useRef<AbortController | undefined>()
|
|
94
130
|
const valuesString = JSON.stringify(defaultValues)
|
|
95
131
|
useEffect(() => {
|
|
96
|
-
if (
|
|
132
|
+
if (!deprecated_useV1) return
|
|
97
133
|
|
|
98
134
|
if (initital.current) {
|
|
99
135
|
initital.current = false
|
|
@@ -104,32 +140,86 @@ export function useFormGql<Q, V extends FieldValues>(
|
|
|
104
140
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
105
141
|
}, [valuesString, form])
|
|
106
142
|
|
|
143
|
+
const beforeSubmit = useEventCallback(
|
|
144
|
+
tryAsync((onBeforeSubmit ?? ((v) => v)) satisfies NonNullable<typeof onBeforeSubmit>),
|
|
145
|
+
)
|
|
146
|
+
const complete = useEventCallback(
|
|
147
|
+
tryAsync((onComplete ?? (() => undefined)) satisfies NonNullable<typeof onComplete>),
|
|
148
|
+
)
|
|
149
|
+
|
|
107
150
|
const handleSubmit: UseFormReturn<V>['handleSubmit'] = (onValid, onInvalid) =>
|
|
108
151
|
form.handleSubmit(async (formValues, event) => {
|
|
109
|
-
|
|
152
|
+
const hasDirtyFields = skipUnchanged
|
|
153
|
+
? Object.values(form?.formState.dirtyFields ?? []).filter(Boolean).length > 0
|
|
154
|
+
: true
|
|
155
|
+
|
|
156
|
+
if (skipUnchanged && !hasDirtyFields) {
|
|
157
|
+
console.log(
|
|
158
|
+
`[useFormGql ${getOperationName(document)}] skipped submission, no dirty fields`,
|
|
159
|
+
)
|
|
160
|
+
await onValid(formValues, event)
|
|
161
|
+
return
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
returnedError.current = undefined
|
|
110
165
|
submittedVariables.current = undefined
|
|
111
|
-
|
|
166
|
+
|
|
167
|
+
// Combine defaults with the formValues and encode
|
|
168
|
+
let variables = !deprecated_useV1 ? formValues : encode({ ...defaultValues, ...formValues })
|
|
112
169
|
|
|
113
170
|
// Wait for the onBeforeSubmit to complete
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
171
|
+
const [onBeforeSubmitResult, onBeforeSubmitError] = await beforeSubmit(variables)
|
|
172
|
+
if (onBeforeSubmitError) {
|
|
173
|
+
if (isApolloError(onBeforeSubmitError)) {
|
|
174
|
+
returnedError.current = onBeforeSubmitError
|
|
175
|
+
} else {
|
|
176
|
+
console.log(
|
|
177
|
+
'A non ApolloError was thrown during the onBeforeSubmit handler.',
|
|
178
|
+
onBeforeSubmitError,
|
|
179
|
+
)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return
|
|
118
183
|
}
|
|
119
|
-
|
|
184
|
+
if (onBeforeSubmitResult === false) return
|
|
185
|
+
variables = onBeforeSubmitResult
|
|
120
186
|
|
|
121
187
|
submittedVariables.current = variables
|
|
122
|
-
if (
|
|
188
|
+
if (!deprecated_useV1 && loading) controllerRef.current?.abort()
|
|
123
189
|
controllerRef.current = new window.AbortController()
|
|
190
|
+
|
|
124
191
|
const result = await execute({
|
|
192
|
+
...operationOptions,
|
|
125
193
|
variables,
|
|
126
|
-
context: {
|
|
194
|
+
context: {
|
|
195
|
+
...operationOptions?.context,
|
|
196
|
+
fetchOptions: {
|
|
197
|
+
...operationOptions?.context?.fetchOptions,
|
|
198
|
+
signal: controllerRef.current.signal,
|
|
199
|
+
},
|
|
200
|
+
},
|
|
127
201
|
})
|
|
128
202
|
|
|
129
|
-
|
|
203
|
+
const [, onCompleteError] = await complete(result, variables)
|
|
204
|
+
if (onCompleteError) {
|
|
205
|
+
returnedError.current = onCompleteError as ApolloError
|
|
206
|
+
return
|
|
207
|
+
}
|
|
208
|
+
if (onCompleteError) {
|
|
209
|
+
if (isApolloError(onCompleteError)) {
|
|
210
|
+
returnedError.current = onCompleteError
|
|
211
|
+
} else {
|
|
212
|
+
console.log(
|
|
213
|
+
'A non ApolloError was thrown during the onComplete handler.',
|
|
214
|
+
onCompleteError,
|
|
215
|
+
)
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
return
|
|
219
|
+
}
|
|
130
220
|
|
|
131
|
-
|
|
132
|
-
|
|
221
|
+
if (deprecated_useV1 && typeof diff(form.getValues(), formValues) === 'undefined')
|
|
222
|
+
// Reset the state of the form if it is unmodified afterwards
|
|
133
223
|
form.reset(formValues)
|
|
134
224
|
|
|
135
225
|
await onValid(formValues, event)
|
|
@@ -139,7 +229,7 @@ export function useFormGql<Q, V extends FieldValues>(
|
|
|
139
229
|
...gqlDocumentHandler,
|
|
140
230
|
handleSubmit,
|
|
141
231
|
data,
|
|
142
|
-
error,
|
|
232
|
+
error: error ?? returnedError.current,
|
|
143
233
|
submittedVariables: submittedVariables.current,
|
|
144
234
|
}
|
|
145
235
|
}
|
|
@@ -45,7 +45,7 @@ export function useFormGqlMutation<Q extends Record<string, unknown>, V extends
|
|
|
45
45
|
): UseFormGqlMutationReturn<Q, V> {
|
|
46
46
|
const form = useForm<V>(options)
|
|
47
47
|
const tuple = useMutation(document, operationOptions)
|
|
48
|
-
const operation = useFormGql({ document, form, tuple, ...options })
|
|
48
|
+
const operation = useFormGql({ document, form, tuple, operationOptions, ...options })
|
|
49
49
|
const muiRegister = useFormMuiRegister(form)
|
|
50
50
|
return { ...form, ...operation, muiRegister, valid: {} }
|
|
51
51
|
}
|
package/src/useFormGqlQuery.tsx
CHANGED
|
@@ -16,7 +16,7 @@ export function useFormGqlQuery<Q extends Record<string, unknown>, V extends Fie
|
|
|
16
16
|
): UseFormGqlQueryReturn<Q, V> {
|
|
17
17
|
const form = useForm<V>(options)
|
|
18
18
|
const tuple = useLazyQuery(document, operationOptions)
|
|
19
|
-
const operation = useFormGql({ document, form, tuple, ...options })
|
|
19
|
+
const operation = useFormGql({ document, form, tuple, operationOptions, ...options })
|
|
20
20
|
const muiRegister = useFormMuiRegister(form)
|
|
21
21
|
|
|
22
22
|
return { ...form, ...operation, valid: {}, muiRegister }
|
package/src/useFormPersist.tsx
CHANGED
|
@@ -39,7 +39,7 @@ export type UseFormPersistOptions<
|
|
|
39
39
|
*
|
|
40
40
|
* Todo: Use wath callback so it won't trigger a rerender
|
|
41
41
|
*
|
|
42
|
-
* @deprecated Please use
|
|
42
|
+
* @deprecated Please use the FormPersist component instead. This method causes INP problems.
|
|
43
43
|
*/
|
|
44
44
|
export function useFormPersist<V extends FieldValues>(options: UseFormPersistOptions<V>) {
|
|
45
45
|
const { form, name, storage = 'sessionStorage', exclude = [], persist = [] } = options
|
|
@@ -98,6 +98,9 @@ export function useFormPersist<V extends FieldValues>(options: UseFormPersistOpt
|
|
|
98
98
|
}, [name, storage, valuesJson])
|
|
99
99
|
}
|
|
100
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Please make sure to always include this component at the end of your form because of useWatch rules: https://react-hook-form.com/docs/usewatch
|
|
103
|
+
*/
|
|
101
104
|
export function FormPersist<V extends FieldValues>(props: UseFormPersistOptions<V>) {
|
|
102
105
|
useFormPersist(props)
|
|
103
106
|
return null
|
package/src/utils/debounce.ts
CHANGED
|
@@ -3,8 +3,24 @@ export interface Cancelable {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export type DebounceOptions = {
|
|
6
|
+
/**
|
|
7
|
+
*
|
|
8
|
+
* Wait for 200 ms after a request before submitting.
|
|
9
|
+
*
|
|
10
|
+
* in milliseconds
|
|
11
|
+
*/
|
|
6
12
|
wait?: number
|
|
13
|
+
/**
|
|
14
|
+
* If there are any pending calls, execute them after this time anyways.
|
|
15
|
+
*
|
|
16
|
+
* in milliseconds
|
|
17
|
+
*/
|
|
7
18
|
maxWait?: number
|
|
19
|
+
/**
|
|
20
|
+
* By default the initialWait is the same as the wait time, but you can set this to a lower value for the initial call.
|
|
21
|
+
*
|
|
22
|
+
* in milliseconds
|
|
23
|
+
*/
|
|
8
24
|
initialWait?: number
|
|
9
25
|
}
|
|
10
26
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const tryAsync =
|
|
2
|
+
<R, Args extends unknown[]>(
|
|
3
|
+
fn: (...args: Args) => Promise<R> | R,
|
|
4
|
+
): ((...args: Args) => Promise<[R, undefined] | [undefined, Error]>) =>
|
|
5
|
+
async (...args: Args) => {
|
|
6
|
+
try {
|
|
7
|
+
return [await fn(...args), undefined]
|
|
8
|
+
} catch (e) {
|
|
9
|
+
console.error(e)
|
|
10
|
+
return [undefined, e as Error]
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const trySync =
|
|
15
|
+
<R, Args extends unknown[]>(
|
|
16
|
+
fn: (...args: Args) => R,
|
|
17
|
+
): ((...args: Args) => [R, undefined] | [undefined, Error]) =>
|
|
18
|
+
(...args: Args) => {
|
|
19
|
+
try {
|
|
20
|
+
return [fn(...args), undefined]
|
|
21
|
+
} catch (e) {
|
|
22
|
+
console.error(e)
|
|
23
|
+
return [undefined, e as Error]
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
|
+
import { useMemoObject } from '@graphcommerce/next-ui/hooks/useMemoObject'
|
|
3
|
+
import useEventCallback from '@mui/utils/useEventCallback'
|
|
4
|
+
import type {
|
|
5
|
+
DebounceSettings,
|
|
6
|
+
DebounceSettingsLeading,
|
|
7
|
+
DebouncedFunc,
|
|
8
|
+
DebouncedFuncLeading,
|
|
9
|
+
} from 'lodash'
|
|
10
|
+
import debounce from 'lodash/debounce'
|
|
11
|
+
import { useMemo } from 'react'
|
|
12
|
+
|
|
13
|
+
export type { DebounceSettings, DebounceSettingsLeading, DebouncedFunc, DebouncedFuncLeading }
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Creates a debounced function that delays invoking func until after wait milliseconds have elapsed since
|
|
17
|
+
* the last time the debounced function was invoked. The debounced function comes with a cancel method to
|
|
18
|
+
* cancel delayed invocations and a flush method to immediately invoke them. Provide an options object to
|
|
19
|
+
* indicate that func should be invoked on the leading and/or trailing edge of the wait timeout. Subsequent
|
|
20
|
+
* calls to the debounced function return the result of the last func invocation.
|
|
21
|
+
*
|
|
22
|
+
* Note: If leading and trailing options are true, func is invoked on the trailing edge of the timeout only
|
|
23
|
+
* if the the debounced function is invoked more than once during the wait timeout.
|
|
24
|
+
*
|
|
25
|
+
* See David Corbacho’s article for details over the differences between _.debounce and _.throttle.
|
|
26
|
+
*
|
|
27
|
+
* @param func The function to debounce.
|
|
28
|
+
* @param wait The number of milliseconds to delay.
|
|
29
|
+
* @param options The options object.
|
|
30
|
+
* @param options.leading Specify invoking on the leading edge of the timeout.
|
|
31
|
+
* @param options.maxWait The maximum time func is allowed to be delayed before it’s invoked.
|
|
32
|
+
* @param options.trailing Specify invoking on the trailing edge of the timeout.
|
|
33
|
+
* @return Returns the new debounced function.
|
|
34
|
+
*/
|
|
35
|
+
export function useDebounce<T extends (...args: never[]) => unknown>(
|
|
36
|
+
func: T,
|
|
37
|
+
wait: number | undefined,
|
|
38
|
+
options: DebounceSettingsLeading,
|
|
39
|
+
): DebouncedFuncLeading<T>
|
|
40
|
+
export function useDebounce<T extends (...args: never[]) => unknown>(
|
|
41
|
+
func: T,
|
|
42
|
+
wait?: number,
|
|
43
|
+
options?: DebounceSettings,
|
|
44
|
+
): DebouncedFunc<T>
|
|
45
|
+
export function useDebounce<T extends (...args: never[]) => unknown>(
|
|
46
|
+
func: T,
|
|
47
|
+
wait?: number,
|
|
48
|
+
options?: DebounceSettings,
|
|
49
|
+
): DebouncedFunc<T> {
|
|
50
|
+
const cb = useEventCallback(func)
|
|
51
|
+
|
|
52
|
+
const opts = useMemoObject(
|
|
53
|
+
Object.fromEntries(Object.entries(options ?? {}).filter(([, v]) => v !== undefined)),
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
return useMemo(() => debounce<T>(cb, wait, opts), [cb, opts, wait])
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export { debounce }
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// eslint-disable-next-line import/no-extraneous-dependencies
|
|
2
1
|
import useEventCallback from '@mui/utils/useEventCallback'
|
|
3
|
-
import {
|
|
2
|
+
import { useMemo } from 'react'
|
|
4
3
|
import debounce, { DebounceOptions } from './debounce'
|
|
5
4
|
|
|
6
5
|
export function useDebouncedCallback<T extends (...args: any[]) => unknown>(
|
|
@@ -9,13 +8,12 @@ export function useDebouncedCallback<T extends (...args: any[]) => unknown>(
|
|
|
9
8
|
): T {
|
|
10
9
|
const func = useEventCallback(callback)
|
|
11
10
|
|
|
12
|
-
const debounced =
|
|
11
|
+
const debounced = useEventCallback(
|
|
12
|
+
useMemo(
|
|
13
|
+
() => debounce({ func, initialWait, maxWait, wait }),
|
|
14
|
+
[func, initialWait, maxWait, wait],
|
|
15
|
+
),
|
|
16
|
+
)
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
useEffect(() => {
|
|
16
|
-
debounced.current = debounce({ func, initialWait, maxWait, wait })
|
|
17
|
-
return () => debounced.current.clear()
|
|
18
|
-
}, [func, initialWait, maxWait, wait])
|
|
19
|
-
|
|
20
|
-
return debounced.current
|
|
18
|
+
return debounced
|
|
21
19
|
}
|