Skip to content
6 changes: 6 additions & 0 deletions .changeset/metal-times-remain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@tanstack/react-form': patch
'@tanstack/react-form-nextjs': patch
---

use React 18's useId hook by default for formId generation, only calling Math.random() as a fallback if no formId is provided.
5 changes: 3 additions & 2 deletions packages/react-form/src/useForm.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
'use client'

import { FormApi, functionalUpdate, uuid } from '@tanstack/form-core'
import { FormApi, functionalUpdate } from '@tanstack/form-core'
import { useStore } from '@tanstack/react-store'
import { useMemo, useState } from 'react'
import { Field } from './useField'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
import { useFormId } from './useFormId'
import type {
AnyFormApi,
AnyFormState,
Expand Down Expand Up @@ -184,7 +185,7 @@ export function useForm<
TSubmitMeta
>,
) {
const fallbackFormId = useState(() => uuid())[0]
const fallbackFormId = useFormId()
const [prevFormId, setPrevFormId] = useState<string>(opts?.formId as never)

const [formApi, setFormApi] = useState(() => {
Expand Down
6 changes: 6 additions & 0 deletions packages/react-form/src/useFormId.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import * as React from 'react'
import { useUUID } from './useUUID'

/** React 17 does not have the useId hook, so we use a random uuid as a fallback. */
export const useFormId =
React.version.split('.')[0] === '17' ? useUUID : React.useId
7 changes: 7 additions & 0 deletions packages/react-form/src/useUUID.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useState } from 'react'
import { uuid } from '@tanstack/form-core'

/** Generates a random UUID. and returns a stable reference to it. */
export function useUUID() {
return useState<string>(() => uuid())[0]
}
Loading