Skip to content

Commit 4cd4068

Browse files
harry-whorlowLeCarbonatorautofix-ci[bot]
authored
fix(react-form): remove useId and adjust types for React 17 compatibility (#1850)
Co-authored-by: LeCarbonator <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 982d7b4 commit 4cd4068

File tree

5 files changed

+54
-32
lines changed

5 files changed

+54
-32
lines changed

.changeset/witty-chefs-greet.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@tanstack/react-form': patch
3+
---
4+
5+
Remove useId for react 17 user compatibility, replaced with uuid

packages/react-form/src/createFormHook.tsx

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ import type {
1717
import type {
1818
ComponentType,
1919
Context,
20+
FunctionComponent,
2021
PropsWithChildren,
21-
ReactNode,
2222
} from 'react'
2323
import type { FieldComponent } from './useField'
2424
import type { ReactFormExtendedApi } from './useForm'
@@ -191,7 +191,10 @@ export type AppFieldExtendedReactFormApi<
191191
TSubmitMeta,
192192
NoInfer<TFieldComponents>
193193
>
194-
AppForm: ComponentType<PropsWithChildren>
194+
AppForm: ComponentType<
195+
// PropsWithChildren<P> is not optional in React 17
196+
PropsWithChildren<{}>
197+
>
195198
}
196199

197200
export interface WithFormProps<
@@ -226,8 +229,8 @@ export interface WithFormProps<
226229
> {
227230
// Optional, but adds props to the `render` function outside of `form`
228231
props?: TRenderProps
229-
render: (
230-
props: PropsWithChildren<
232+
render: FunctionComponent<
233+
PropsWithChildren<
231234
NoInfer<TRenderProps> & {
232235
form: AppFieldExtendedReactFormApi<
233236
TFormData,
@@ -246,8 +249,8 @@ export interface WithFormProps<
246249
TFormComponents
247250
>
248251
}
249-
>,
250-
) => ReactNode
252+
>
253+
>
251254
}
252255

253256
export interface WithFieldGroupProps<
@@ -259,8 +262,8 @@ export interface WithFieldGroupProps<
259262
> extends BaseFormOptions<TFieldGroupData, TSubmitMeta> {
260263
// Optional, but adds props to the `render` function outside of `form`
261264
props?: TRenderProps
262-
render: (
263-
props: PropsWithChildren<
265+
render: FunctionComponent<
266+
PropsWithChildren<
264267
NoInfer<TRenderProps> & {
265268
group: AppFieldExtendedReactFieldGroupApi<
266269
unknown,
@@ -283,8 +286,8 @@ export interface WithFieldGroupProps<
283286
TFormComponents
284287
>
285288
}
286-
>,
287-
) => ReactNode
289+
>
290+
>
288291
}
289292

290293
export function createFormHook<
@@ -342,13 +345,13 @@ export function createFormHook<
342345
> {
343346
const form = useForm(props)
344347

345-
const AppForm = useMemo(() => {
346-
const AppForm = (({ children }) => {
348+
// PropsWithChildren<P> is not optional in React 17
349+
const AppForm = useMemo<ComponentType<PropsWithChildren<{}>>>(() => {
350+
return ({ children }) => {
347351
return (
348352
<formContext.Provider value={form}>{children}</formContext.Provider>
349353
)
350-
}) as ComponentType<PropsWithChildren>
351-
return AppForm
354+
}
352355
}, [form])
353356

354357
const AppField = useMemo(() => {
@@ -521,7 +524,7 @@ export function createFormHook<
521524
fields: TFields
522525
}
523526
>,
524-
) => ReactNode {
527+
) => ReturnType<FunctionComponent> {
525528
return function Render(innerProps) {
526529
const fieldGroupProps = useMemo(() => {
527530
return {

packages/react-form/src/useField.tsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import type {
1313
FormAsyncValidateOrFn,
1414
FormValidateOrFn,
1515
} from '@tanstack/form-core'
16-
import type { FunctionComponent, ReactNode } from 'react'
16+
import type { FunctionComponent, ReactElement, ReactNode } from 'react'
1717
import type { UseFieldOptions, UseFieldOptionsBound } from './types'
1818

1919
interface ReactFieldApi<
@@ -496,7 +496,7 @@ export type FieldComponent<
496496
TFormOnServer,
497497
TPatentSubmitMeta,
498498
ExtendedApi
499-
>) => ReactNode
499+
>) => ReturnType<FunctionComponent>
500500

501501
/**
502502
* A type alias representing a field component for a form lens data type.
@@ -584,7 +584,7 @@ export type LensFieldComponent<
584584
*/
585585
onBlurListenTo?: DeepKeys<TLensData>[]
586586
}
587-
}) => ReactNode
587+
}) => ReturnType<FunctionComponent>
588588

589589
/**
590590
* A function component that takes field options and a render function as children and returns a React component.
@@ -650,7 +650,7 @@ export const Field = (<
650650
TFormOnDynamicAsync,
651651
TFormOnServer,
652652
TPatentSubmitMeta
653-
>): ReactNode => {
653+
>): ReturnType<FunctionComponent> => {
654654
const fieldApi = useField(fieldOptions as any)
655655

656656
const jsxToDisplay = useMemo(

packages/react-form/src/useFieldGroup.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,12 @@ import type {
1313
FormValidateOrFn,
1414
} from '@tanstack/form-core'
1515
import type { AppFieldExtendedReactFormApi } from './createFormHook'
16-
import type { ComponentType, PropsWithChildren, ReactNode } from 'react'
16+
import type {
17+
ComponentType,
18+
FunctionComponent,
19+
PropsWithChildren,
20+
ReactNode,
21+
} from 'react'
1722
import type { LensFieldComponent } from './useField'
1823

1924
function LocalSubscribe({
@@ -23,10 +28,10 @@ function LocalSubscribe({
2328
}: PropsWithChildren<{
2429
lens: AnyFieldGroupApi
2530
selector: (state: FieldGroupState<any>) => FieldGroupState<any>
26-
}>) {
31+
}>): ReturnType<FunctionComponent> {
2732
const data = useStore(lens.store, selector)
2833

29-
return functionalUpdate(children, data)
34+
return <>{functionalUpdate(children, data)}</>
3035
}
3136

3237
/**
@@ -73,7 +78,7 @@ export type AppFieldExtendedReactFieldGroupApi<
7378
TSubmitMeta,
7479
NoInfer<TFieldComponents>
7580
>
76-
AppForm: ComponentType<PropsWithChildren>
81+
AppForm: ComponentType<PropsWithChildren<{}>>
7782
/**
7883
* A React component to render form fields. With this, you can render and manage individual form fields.
7984
*/
@@ -85,7 +90,7 @@ export type AppFieldExtendedReactFieldGroupApi<
8590
Subscribe: <TSelected = NoInfer<FieldGroupState<TFieldGroupData>>>(props: {
8691
selector?: (state: NoInfer<FieldGroupState<TFieldGroupData>>) => TSelected
8792
children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode
88-
}) => ReactNode
93+
}) => ReturnType<FunctionComponent>
8994
}
9095

9196
export function useFieldGroup<

packages/react-form/src/useForm.tsx

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
'use client'
22

3-
import { FormApi, functionalUpdate } from '@tanstack/form-core'
3+
import { FormApi, functionalUpdate, uuid } from '@tanstack/form-core'
44
import { useStore } from '@tanstack/react-store'
5-
import { useId, useState } from 'react'
5+
import { useRef, useState } from 'react'
66
import { Field } from './useField'
77
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
88
import type {
@@ -13,7 +13,12 @@ import type {
1313
FormState,
1414
FormValidateOrFn,
1515
} from '@tanstack/form-core'
16-
import type { PropsWithChildren, ReactNode } from 'react'
16+
import type {
17+
FunctionComponent,
18+
PropsWithChildren,
19+
ReactElement,
20+
ReactNode,
21+
} from 'react'
1722
import type { FieldComponent } from './useField'
1823
import type { NoInfer } from '@tanstack/react-store'
1924

@@ -89,7 +94,7 @@ export interface ReactFormApi<
8994
>,
9095
) => TSelected
9196
children: ((state: NoInfer<TSelected>) => ReactNode) | ReactNode
92-
}) => ReactNode
97+
}) => ReturnType<FunctionComponent>
9398
}
9499

95100
/**
@@ -144,10 +149,10 @@ function LocalSubscribe({
144149
}: PropsWithChildren<{
145150
form: AnyFormApi
146151
selector: (state: AnyFormState) => AnyFormState
147-
}>) {
152+
}>): ReturnType<FunctionComponent> {
148153
const data = useStore(form.store, selector)
149154

150-
return functionalUpdate(children, data)
155+
return <>{functionalUpdate(children, data)}</>
151156
}
152157

153158
/**
@@ -184,7 +189,11 @@ export function useForm<
184189
TSubmitMeta
185190
>,
186191
) {
187-
const formId = useId()
192+
const formId = useRef<string>(opts?.formId as never)
193+
194+
if (!formId.current) {
195+
formId.current = uuid()
196+
}
188197

189198
const [formApi] = useState(() => {
190199
const api = new FormApi<
@@ -200,7 +209,7 @@ export function useForm<
200209
TOnDynamicAsync,
201210
TOnServer,
202211
TSubmitMeta
203-
>({ ...opts, formId: formId })
212+
>({ ...opts, formId: formId.current })
204213

205214
const extendedApi: ReactFormExtendedApi<
206215
TFormData,

0 commit comments

Comments
 (0)