Skip to content

Commit 4bf648a

Browse files
committed
feat: move to useMerge away from useTransform
1 parent c70194a commit 4bf648a

File tree

11 files changed

+345
-217
lines changed

11 files changed

+345
-217
lines changed
Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
1-
'use client';
1+
'use client'
22

3-
import { useActionState, useLayoutEffect } from 'react'
4-
import { mergeForm, useForm } from '@tanstack/react-form-nextjs';
5-
import { initialFormState, useTransform } from '@tanstack/react-form-nextjs';
6-
import someAction from './action';
7-
import { formOpts } from './shared-code';
8-
import { z } from 'zod';
3+
import { useActionState } from 'react'
4+
import {
5+
initialFormState,
6+
mergeForm,
7+
useForm,
8+
useMerge,
9+
} from '@tanstack/react-form-nextjs'
10+
import { z } from 'zod'
11+
import someAction from './action'
12+
import { formOpts } from './shared-code'
913

1014
export const ClientComp = () => {
11-
const [state, action] = useActionState(someAction, initialFormState);
12-
13-
// debugger
15+
const [state, action] = useActionState(someAction, initialFormState)
1416

1517
const form = useForm({
1618
...formOpts,
17-
transform: useTransform(
18-
(baseForm) => mergeForm(baseForm, state ?? {}),
19-
[state]
20-
),
21-
});
19+
})
2220

23-
useLayoutEffect(() => {
24-
form.mergeAndUpdate()
25-
}, [state])
21+
useMerge({
22+
form,
23+
fn: (baseForm) => mergeForm(baseForm, state ?? {}),
24+
deps: [state],
25+
})
2626

2727
return (
2828
<form action={action as never} onSubmit={() => form.handleSubmit()}>
@@ -45,7 +45,7 @@ export const ClientComp = () => {
4545
<p key={error?.message ?? ''}>{error?.message}</p>
4646
))}
4747
</div>
48-
);
48+
)
4949
}}
5050
</form.Field>
5151
<form.Subscribe
@@ -58,5 +58,5 @@ export const ClientComp = () => {
5858
)}
5959
</form.Subscribe>
6060
</form>
61-
);
62-
};
61+
)
62+
}

packages/form-core/src/FormApi.ts

Lines changed: 1 addition & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -217,54 +217,6 @@ export interface FormValidators<
217217
onDynamicAsyncDebounceMs?: number
218218
}
219219

220-
/**
221-
* @private
222-
*/
223-
export interface FormTransform<
224-
TFormData,
225-
TOnMount extends undefined | FormValidateOrFn<TFormData>,
226-
TOnChange extends undefined | FormValidateOrFn<TFormData>,
227-
TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
228-
TOnBlur extends undefined | FormValidateOrFn<TFormData>,
229-
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
230-
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
231-
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
232-
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
233-
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
234-
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
235-
TSubmitMeta = never,
236-
> {
237-
fn: (
238-
formBase: FormApi<
239-
TFormData,
240-
TOnMount,
241-
TOnChange,
242-
TOnChangeAsync,
243-
TOnBlur,
244-
TOnBlurAsync,
245-
TOnSubmit,
246-
TOnSubmitAsync,
247-
TOnDynamic,
248-
TOnDynamicAsync,
249-
TOnServer,
250-
TSubmitMeta
251-
>,
252-
) => FormApi<
253-
TFormData,
254-
TOnMount,
255-
TOnChange,
256-
TOnChangeAsync,
257-
TOnBlur,
258-
TOnBlurAsync,
259-
TOnSubmit,
260-
TOnSubmitAsync,
261-
TOnDynamic,
262-
TOnDynamicAsync,
263-
TOnServer,
264-
TSubmitMeta
265-
>
266-
}
267-
268220
export interface FormListeners<
269221
TFormData,
270222
TOnMount extends undefined | FormValidateOrFn<TFormData>,
@@ -496,20 +448,6 @@ export interface FormOptions<
496448
>
497449
meta: TSubmitMeta
498450
}) => void
499-
transform?: FormTransform<
500-
NoInfer<TFormData>,
501-
NoInfer<TOnMount>,
502-
NoInfer<TOnChange>,
503-
NoInfer<TOnChangeAsync>,
504-
NoInfer<TOnBlur>,
505-
NoInfer<TOnBlurAsync>,
506-
NoInfer<TOnSubmit>,
507-
NoInfer<TOnSubmitAsync>,
508-
NoInfer<TOnDynamic>,
509-
NoInfer<TOnDynamicAsync>,
510-
NoInfer<TOnServer>,
511-
NoInfer<TSubmitMeta>
512-
>
513451
}
514452

515453
export type AnyFormOptions = FormOptions<
@@ -657,7 +595,7 @@ export type BaseFormState<
657595
_force_re_eval?: boolean
658596
}
659597

660-
type AnyBaseFormState = BaseFormState<
598+
export type AnyBaseFormState = BaseFormState<
661599
any,
662600
any,
663601
any,
@@ -977,11 +915,6 @@ export class FormApi<
977915
return this.store.state
978916
}
979917

980-
/**
981-
* @private
982-
*/
983-
prevTransformArray: unknown[] = []
984-
985918
/**
986919
* @private
987920
*/
@@ -2591,62 +2524,6 @@ export class FormApi<
25912524
})
25922525
}
25932526

2594-
mergeAndUpdate = () => {
2595-
// Run the `transform` function on `this.state`, diff it, and update the relevant parts with what needs updating
2596-
if (!this.options.transform?.fn) return
2597-
2598-
const newObj = Object.assign({}, this, {
2599-
// structuredClone is required to avoid `state` being mutated outside of this block
2600-
// Commonly available since 2022 in all major browsers BUT NOT REACT NATIVE NOOOOOOO
2601-
state: structuredClone(this.state),
2602-
})
2603-
2604-
this.options.transform.fn(newObj)
2605-
2606-
if (newObj.fieldInfo !== this.fieldInfo) {
2607-
this.fieldInfo = newObj.fieldInfo
2608-
}
2609-
2610-
if (newObj.options !== this.options) {
2611-
this.options = newObj.options
2612-
}
2613-
2614-
const baseFormKeys = Object.keys({
2615-
values: null,
2616-
validationMetaMap: null,
2617-
fieldMetaBase: null,
2618-
isSubmitting: null,
2619-
isSubmitted: null,
2620-
isValidating: null,
2621-
submissionAttempts: null,
2622-
isSubmitSuccessful: null,
2623-
_force_re_eval: null,
2624-
// Do not remove this, it ensures that we have all the keys in `BaseFormState`
2625-
} satisfies Record<
2626-
// Exclude errorMap since we need to handle that uniquely
2627-
Exclude<keyof AnyBaseFormState, 'errorMap'>,
2628-
null
2629-
>) as Array<keyof AnyBaseFormState>
2630-
2631-
const diffedObject = baseFormKeys.reduce((prev, key) => {
2632-
if (this.state[key] !== newObj.state[key]) {
2633-
prev[key] = newObj.state[key]
2634-
}
2635-
return prev
2636-
}, {} as Partial<AnyBaseFormState>)
2637-
2638-
batch(() => {
2639-
if (Object.keys(diffedObject).length) {
2640-
this.baseStore.setState((prev) => ({ ...prev, ...diffedObject }))
2641-
}
2642-
2643-
if (newObj.state.errorMap !== this.state.errorMap) {
2644-
// Check if we need to update `fieldMetaBase` with `errorMaps` set by
2645-
this.setErrorMap(newObj.state.errorMap)
2646-
}
2647-
})
2648-
}
2649-
26502527
/**
26512528
* Returns form and field level errors
26522529
*/

packages/form-core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export * from './standardSchemaValidator'
99
export * from './FieldGroupApi'
1010
export * from './ValidationLogic'
1111
export * from './EventClient'
12+
export * from './transform'

packages/form-core/src/mergeForm.ts

Lines changed: 42 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { FormApi } from './FormApi'
1+
import type {
2+
FormApi,
3+
FormAsyncValidateOrFn,
4+
FormValidateOrFn,
5+
} from './FormApi'
26

37
function isValidKey(key: string | number | symbol): boolean {
48
const dangerousProps = ['__proto__', 'constructor', 'prototype']
@@ -70,35 +74,48 @@ export function mutateMergeDeep(
7074
return target
7175
}
7276

73-
export function mergeForm<TFormData>(
77+
export function mergeForm<
78+
TFormData,
79+
TOnMount extends undefined | FormValidateOrFn<TFormData>,
80+
TOnChange extends undefined | FormValidateOrFn<TFormData>,
81+
TOnChangeAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
82+
TOnBlur extends undefined | FormValidateOrFn<TFormData>,
83+
TOnBlurAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
84+
TOnSubmit extends undefined | FormValidateOrFn<TFormData>,
85+
TOnSubmitAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
86+
TOnDynamic extends undefined | FormValidateOrFn<TFormData>,
87+
TOnDynamicAsync extends undefined | FormAsyncValidateOrFn<TFormData>,
88+
TOnServer extends undefined | FormAsyncValidateOrFn<TFormData>,
89+
TSubmitMeta = never,
90+
>(
7491
baseForm: FormApi<
75-
NoInfer<TFormData>,
76-
any,
77-
any,
78-
any,
79-
any,
80-
any,
81-
any,
82-
any,
83-
any,
84-
any,
85-
any,
86-
any
92+
TFormData,
93+
TOnMount,
94+
TOnChange,
95+
TOnChangeAsync,
96+
TOnBlur,
97+
TOnBlurAsync,
98+
TOnSubmit,
99+
TOnSubmitAsync,
100+
TOnDynamic,
101+
TOnDynamicAsync,
102+
TOnServer,
103+
TSubmitMeta
87104
>,
88105
state: Partial<
89106
FormApi<
90107
TFormData,
91-
any,
92-
any,
93-
any,
94-
any,
95-
any,
96-
any,
97-
any,
98-
any,
99-
any,
100-
any,
101-
any
108+
TOnMount,
109+
TOnChange,
110+
TOnChangeAsync,
111+
TOnBlur,
112+
TOnBlurAsync,
113+
TOnSubmit,
114+
TOnSubmitAsync,
115+
TOnDynamic,
116+
TOnDynamicAsync,
117+
TOnServer,
118+
TSubmitMeta
102119
>['state']
103120
>,
104121
) {

0 commit comments

Comments
 (0)