@@ -74,7 +74,6 @@ function PydanticFormContextProvider({
7474 new Map < string , object > ( ) ,
7575 ) ;
7676 const [ formInputData , setFormInputData ] = useState < object [ ] > ( [ ] ) ;
77-
7877 const formRef = useRef < string > ( formKey ) ;
7978
8079 const updateHistory = useCallback (
@@ -166,58 +165,46 @@ function PydanticFormContextProvider({
166165
167166 /*
168167 This method resets the form and makes sure it waits for the reset to complete
169- before proceeding. If it finds data in form history, it uses that data to reset the form.
168+ before proceeding. If it finds data in formHistory based on the hash of the previo
169+ us steps, it uses that data to prefill the form.
170170 */
171- const awaitReset = useCallback (
172- async ( payLoad ?: FieldValues ) => {
173- await getHashForArray ( formInputData ) . then ( ( hash ) => {
171+ const awaitReset = useCallback ( async ( payLoad ?: FieldValues ) => {
172+ await getHashForArray ( formInputData )
173+ . then ( ( hash ) => {
174174 let resetPayload = { } ;
175175
176176 if ( payLoad ) {
177177 resetPayload = { ...payLoad } ;
178- } else {
179- const currentStepFromHistory = formInputHistory . get ( hash ) ;
180-
181- if ( currentStepFromHistory ) {
182- resetPayload = { ...currentStepFromHistory } ;
183- }
184178 }
179+
185180 reactHookForm . reset ( resetPayload ) ;
181+ } )
182+ . catch ( ( ) => {
183+ console . error ( 'Failed to hash form input data' ) ;
186184 } ) ;
187- } ,
188-
189- [ formInputData , formInputHistory , reactHookForm ] ,
190- ) ;
185+ } , [ ] ) ;
191186
192- const addFormInputData = useCallback (
193- ( formInput : object , replaceInsteadOfAdd = false ) => {
194- setFormInputData ( ( currentInputs ) => {
195- const data = replaceInsteadOfAdd
196- ? currentInputs . slice ( 0 , - 1 )
197- : currentInputs ;
198- updateHistory ( formInput , data ) ;
199- return [ ...data , { ...formInput } ] ;
200- } ) ;
201- awaitReset ( ) ;
202- } ,
203- [ awaitReset , setFormInputData , updateHistory ] ,
204- ) ;
187+ const addFormInputData = useCallback ( ( ) => {
188+ setFormInputData ( ( currentInputs ) => {
189+ // Note. If we don't use cloneDeep here we are adding a reference to the reactHookFormValues
190+ // that changes on every change in the form and triggering effects before we want to.
191+ const reactHookFormValues = _ . cloneDeep ( reactHookForm . getValues ( ) ) ;
192+ updateHistory ( reactHookFormValues , currentInputs ) ;
193+ return [ ...currentInputs , { ...reactHookFormValues } ] ;
194+ } ) ;
195+ // setInErrorState(false);
196+ // We call reset right after using the values to make sure
197+ // values in reactHookForm are cleared. This avoids some
198+ // race condition errors where reacfHookForm data was still set where we did not
199+ /// expect it to be.
200+ awaitReset ( ) ;
201+ } , [ ] ) ;
205202
206203 const submitFormFn = useCallback ( ( ) => {
207204 setIsSending ( true ) ;
208- const reactHookFormValues = _ . cloneDeep ( reactHookForm . getValues ( ) ) ;
209- awaitReset ( ) ;
210- // Note. If we don't use cloneDeep here we are adding a reference to the reactHookFormValues
211- // that changes on every change in the form and triggering effects before we want to.
212- addFormInputData ( reactHookFormValues , ! ! errorDetails ) ;
205+ addFormInputData ( ) ;
213206 window . scrollTo ( 0 , 0 ) ;
214- } , [
215- reactHookForm ,
216- errorDetails ,
217- addFormInputData ,
218- awaitReset ,
219- setIsSending ,
220- ] ) ;
207+ } , [ ] ) ;
221208
222209 const onClientSideError = useCallback (
223210 ( data ?: FieldValues ) => {
@@ -245,23 +232,12 @@ function PydanticFormContextProvider({
245232 [ awaitReset , reactHookForm ] ,
246233 ) ;
247234
248- const resetErrorDetails = useCallback ( ( ) => {
249- setErrorDetails ( undefined ) ;
250- } , [ ] ) ;
251-
252235 const isLoading =
253236 isLoadingFormLabels ||
254237 isLoadingSchema ||
255238 isParsingSchema ||
256239 ( customDataProvider ? isLoadingCustomData : false ) ;
257240
258- const clearForm = useCallback ( ( ) => {
259- setFormInputData ( [ ] ) ;
260- setIsFullFilled ( false ) ;
261- setRawSchema ( emptyRawSchema ) ;
262- setHasNext ( false ) ;
263- } , [ emptyRawSchema ] ) ;
264-
265241 const fieldDataStorageRef = useRef < Map < string , Map < string , unknown > > > (
266242 new Map ( ) ,
267243 ) ;
@@ -299,9 +275,6 @@ function PydanticFormContextProvider({
299275 ) ;
300276
301277 const PydanticFormContextState = {
302- // to prevent an issue where the sending state hangs
303- // we check both the SWR hook state as our manual state
304- clearForm,
305278 config,
306279 customDataProvider,
307280 errorDetails,
@@ -317,7 +290,6 @@ function PydanticFormContextProvider({
317290 onPrevious : ( ) => goToPreviousStep ( reactHookForm ?. getValues ( ) ) ,
318291 pydanticFormSchema,
319292 reactHookForm,
320- resetErrorDetails,
321293 resetForm,
322294 submitForm,
323295 title,
@@ -332,23 +304,29 @@ function PydanticFormContextProvider({
332304 if ( apiResponse ?. validation_errors ) {
333305 // Restore the data we got the error with
334306 const errorPayload = [ ...formInputData ] . pop ( ) ;
307+ setFormInputData ( ( currentData ) => {
308+ const newData = [ ...currentData ] ;
309+ newData . pop ( ) ;
310+ return newData ;
311+ } ) ;
335312 awaitReset ( errorPayload ) ;
336313 setErrorDetails ( getErrorDetailsFromResponse ( apiResponse ) ) ;
337314 return ;
338315 }
339316
340- awaitReset ( ) ;
341317 if ( apiResponse ?. success ) {
342318 setIsFullFilled ( true ) ;
343319 return ;
344320 }
345321
346322 // when we receive a new form from JSON, we fully reset the form
347323 if ( apiResponse ?. form && rawSchema !== apiResponse . form ) {
324+ awaitReset ( ) ;
348325 setRawSchema ( apiResponse . form ) ;
349326 if ( apiResponse . meta ) {
350327 setHasNext ( ! ! apiResponse . meta . hasNext ) ;
351328 }
329+
352330 setErrorDetails ( undefined ) ;
353331 }
354332
@@ -361,10 +339,9 @@ function PydanticFormContextProvider({
361339 if ( formKey !== formRef . current ) {
362340 setFormInputData ( [ ] ) ;
363341 setFormInputHistory ( new Map < string , object > ( ) ) ;
364- awaitReset ( { } ) ;
365342 formRef . current = formKey ;
366343 }
367- } , [ awaitReset , formKey ] ) ;
344+ } , [ formKey ] ) ;
368345
369346 // UseEffect to handle successfull submits
370347 useEffect ( ( ) => {
@@ -379,7 +356,7 @@ function PydanticFormContextProvider({
379356
380357 setFormInputHistory ( new Map < string , object > ( ) ) ;
381358 // eslint-disable-next-line react-hooks/exhaustive-deps
382- } , [ apiResponse , isFullFilled ] ) ; // Avoid completing the dependencies array here to avoid unwanted resetFormData calls
359+ } , [ isFullFilled ] ) ; // Avoid completing the dependencies array here to avoid unwanted resetFormData calls
383360
384361 // UseEffect to handles errors throws by the useApiProvider call
385362 // for instance unexpected 500 errors
0 commit comments