- {store.formState.length > 0 && (
+ {store().length > 0 && (
-
+
{(instance) => {
return (
}
-type DevtoolsState = {
- formState: Array
-}
-
-const devtoolsStateInit: DevtoolsState = {
- formState: [],
-}
-
function useProviderValue() {
- const [store, setStore] = createStore(devtoolsStateInit)
+ const [store, setStore] = createStore>([])
createEffect(() => {
- const cleanup = formEventClient.on('form-state-change', (e) => {
- setStore('formState', (prev) => {
- const existing = prev.find((item) => item.id === e.payload.id)
-
- if (existing) {
- return prev.map((item) =>
- item.id === e.payload.id
- ? {
- ...item,
- state: e.payload.state,
- options: e.payload.options,
- date: dayjs(),
- }
- : item,
- )
- }
-
- return [
+ const cleanup = formEventClient.on('form-api', (e) => {
+ const id = e.payload.id
+ const existingIndex = store.findIndex((item) => item.id === id)
+
+ if (existingIndex > -1) {
+ setStore(existingIndex, {
+ state: e.payload.state,
+ options: e.payload.options,
+ date: dayjs(),
+ })
+ } else {
+ setStore((prev) => [
...prev,
{
- id: e.payload.id,
+ id,
state: e.payload.state,
options: e.payload.options,
date: dayjs(),
history: [],
},
- ]
- })
+ ])
+ }
+ })
+
+ onCleanup(cleanup)
+ })
+
+ createEffect(() => {
+ const cleanup = formEventClient.on('form-state', (e) => {
+ const id = e.payload.id
+ const existingIndex = store.findIndex((item) => item.id === id)
+
+ if (existingIndex > -1) {
+ setStore(existingIndex, {
+ state: e.payload.state,
+ date: dayjs(),
+ })
+ } else {
+ setStore((prev) => [
+ ...prev,
+ {
+ id,
+ state: e.payload.state,
+ options: {},
+ date: dayjs(),
+ history: [],
+ },
+ ])
+ }
})
- onCleanup(() => cleanup())
+ onCleanup(cleanup)
})
createEffect(() => {
- const cleanup = formEventClient.on('form-submission-state-change', (e) => {
- setStore('formState', (prev) =>
- prev.map((item) => {
- if (item.id !== e.payload.id) return item
-
- const { id, ...rest } = e.payload
- const newHistory = [rest, ...item.history].slice(0, 5)
-
- return {
- ...item,
- history: newHistory,
- }
- }),
- )
+ const cleanup = formEventClient.on('form-submission', (e) => {
+ const id = e.payload.id
+ const existingIndex = store.findIndex((item) => item.id === id)
+
+ if (existingIndex > -1 && store[existingIndex]) {
+ const { id: _, ...rest } = e.payload
+ const newHistory = [rest, ...store[existingIndex].history].slice(0, 5)
+ setStore(existingIndex, 'history', newHistory)
+ }
})
- onCleanup(() => cleanup())
+ onCleanup(cleanup)
})
createEffect(() => {
const cleanup = formEventClient.on('form-unmounted', (e) => {
- setStore('formState', (prev) =>
- prev.filter((item) => item.id !== e.payload.id),
- )
+ setStore((prev) => prev.filter((item) => item.id !== e.payload.id))
})
- onCleanup(() => cleanup())
+ onCleanup(cleanup)
})
return { store }
@@ -127,5 +139,6 @@ export function useFormEventClient() {
)
}
- return context
+ const memoContext = createMemo(() => context.store)
+ return { store: memoContext }
}
diff --git a/packages/react-form/src/useForm.tsx b/packages/react-form/src/useForm.tsx
index ddfc5ceb2..d0175f8c4 100644
--- a/packages/react-form/src/useForm.tsx
+++ b/packages/react-form/src/useForm.tsx
@@ -1,8 +1,9 @@
import { FormApi, functionalUpdate } from '@tanstack/form-core'
import { useStore } from '@tanstack/react-store'
-import { useState } from 'react'
+import { useRef, useState } from 'react'
import { Field } from './useField'
import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect'
+import { uuid } from './utils'
import type {
AnyFormApi,
AnyFormState,
@@ -182,6 +183,7 @@ export function useForm<
TSubmitMeta
>,
) {
+ const ref = useRef(opts?.formId ?? uuid())
const [formApi] = useState(() => {
const api = new FormApi<
TFormData,
@@ -196,7 +198,7 @@ export function useForm<
TOnDynamicAsync,
TOnServer,
TSubmitMeta
- >(opts)
+ >({ ...opts, formId: ref.current })
const extendedApi: ReactFormExtendedApi<
TFormData,
diff --git a/packages/react-form/src/utils.ts b/packages/react-form/src/utils.ts
new file mode 100644
index 000000000..9ba47a7a3
--- /dev/null
+++ b/packages/react-form/src/utils.ts
@@ -0,0 +1,35 @@
+let IDX = 256
+const HEX: string[] = []
+let BUFFER: number[] | undefined
+
+while (IDX--) {
+ HEX[IDX] = (IDX + 256).toString(16).substring(1)
+}
+
+export function uuid(): string {
+ let i = 0
+ let num: number
+ let out = ''
+
+ if (!BUFFER || IDX + 16 > 256) {
+ BUFFER = new Array(256)
+ i = 256
+ while (i--) {
+ BUFFER[i] = (256 * Math.random()) | 0
+ }
+ i = 0
+ IDX = 0
+ }
+
+ for (; i < 16; i++) {
+ num = BUFFER[IDX + i] as number
+ if (i === 6) out += HEX[(num & 15) | 64]
+ else if (i === 8) out += HEX[(num & 63) | 128]
+ else out += HEX[num]
+
+ if (i & 1 && i > 1 && i < 11) out += '-'
+ }
+
+ IDX++
+ return out
+}
\ No newline at end of file
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bd422bbbd..6d8583832 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -387,7 +387,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -449,7 +449,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -480,7 +480,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -514,7 +514,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -545,7 +545,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -607,7 +607,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -687,7 +687,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -718,7 +718,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -761,7 +761,7 @@ importers:
dependencies:
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -825,7 +825,7 @@ importers:
version: 6.5.0(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@emotion/styled@11.14.1(@emotion/react@11.14.0(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react@19.1.0))(@types/react@19.1.6)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)
'@tanstack/react-devtools':
specifier: ^0.6.4
- version: 0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
+ version: 0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)
'@tanstack/react-form':
specifier: ^1.23.0
version: link:../../../packages/react-form
@@ -1183,6 +1183,9 @@ importers:
'@tanstack/devtools-event-client':
specifier: ^0.2.5
version: 0.2.5
+ '@tanstack/pacer':
+ specifier: ^0.15.3
+ version: 0.15.3
'@tanstack/store':
specifier: ^0.7.5
version: 0.7.5
@@ -1203,8 +1206,8 @@ importers:
packages/form-devtools:
dependencies:
'@tanstack/devtools-ui':
- specifier: ^0.3.5
- version: 0.3.5(csstype@3.1.3)(solid-js@1.9.9)
+ specifier: ^0.4.0
+ version: 0.4.0(csstype@3.1.3)(solid-js@1.9.9)
'@tanstack/form-core':
specifier: workspace:*
version: link:../form-core
@@ -4860,8 +4863,8 @@ packages:
resolution: {integrity: sha512-iVdqw879KETXyyPHc3gQR5Ld0GjlPLk7bKenBUhzr3+z1FiQZvsbfgYfRRokTSPcgwANAV7aA2Uv05nx5xWT8A==}
engines: {node: '>=18'}
- '@tanstack/devtools-ui@0.3.5':
- resolution: {integrity: sha512-DU8OfLntngnph+Tb7ivQvh4F4w+rDu6r01fXlhjq/Nmgdr0gtsOox4kdmyq5rCs+C6aPgP3M7+BE+fv4dN+VvA==}
+ '@tanstack/devtools-ui@0.4.0':
+ resolution: {integrity: sha512-kiCfKnfuPWz1VWOKIr3kkWXMMvwu6GOR/SSu2AjTOu/CxkDSl57DVvOHJDNE6PDd5gN7JPn/46R9Rg8jcrR6nA==}
engines: {node: '>=18'}
peerDependencies:
solid-js: '>=1.9.7'
@@ -4887,6 +4890,10 @@ packages:
resolution: {integrity: sha512-cs1WKawpXIe+vSTeiZUuSBy8JFjEuDgdMKZFRLKwQysKo8y2q6Q1HvS74Yw+m5IhOW1nTZooa6rlgdfXcgFAaw==}
engines: {node: '>=12'}
+ '@tanstack/pacer@0.15.3':
+ resolution: {integrity: sha512-yF7TDPeCwss+4zlHAinBDUrG+RF4+f3oUedYsTEcyXSdgTLLwozFxA1nH72KugTE67A1BkpfSrgeMjDYHgaaPw==}
+ engines: {node: '>=18'}
+
'@tanstack/publish-config@0.2.0':
resolution: {integrity: sha512-RC0yRBFJvGuR58tKQUIkMXVEiATXgESIc+3/NTqoCC7D2YOF4fZGmHGYIanFEPQH7EGfQ5+Bwi+H6BOtKnymtw==}
engines: {node: '>=18'}
@@ -15619,7 +15626,7 @@ snapshots:
'@tanstack/devtools-event-client@0.2.5': {}
- '@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9)':
+ '@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9)':
dependencies:
clsx: 2.1.1
goober: 2.1.16(csstype@3.1.3)
@@ -15627,11 +15634,11 @@ snapshots:
transitivePeerDependencies:
- csstype
- '@tanstack/devtools@0.6.8(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(csstype@3.1.3)(solid-js@1.9.9)':
+ '@tanstack/devtools@0.6.8(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(csstype@3.1.3)(solid-js@1.9.9)':
dependencies:
'@solid-primitives/keyboard': 1.3.3(solid-js@1.9.9)
'@tanstack/devtools-event-bus': 0.3.2
- '@tanstack/devtools-ui': 0.3.5(csstype@3.1.3)(solid-js@1.9.9)
+ '@tanstack/devtools-ui': 0.4.0(csstype@3.1.3)(solid-js@1.9.9)
clsx: 2.1.1
goober: 2.1.16(csstype@3.1.3)
solid-js: 1.9.9
@@ -15671,6 +15678,11 @@ snapshots:
'@tanstack/history@1.131.2': {}
+ '@tanstack/pacer@0.15.3':
+ dependencies:
+ '@tanstack/devtools-event-client': 0.2.5
+ '@tanstack/store': 0.7.5
+
'@tanstack/publish-config@0.2.0':
dependencies:
'@commitlint/parse': 19.8.1
@@ -15682,9 +15694,9 @@ snapshots:
'@tanstack/query-core@5.89.0': {}
- '@tanstack/react-devtools@0.6.4(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)':
+ '@tanstack/react-devtools@0.6.4(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(@types/react-dom@19.1.5(@types/react@19.1.6))(@types/react@19.1.6)(csstype@3.1.3)(react-dom@19.1.0(react@19.1.0))(react@19.1.0)(solid-js@1.9.9)':
dependencies:
- '@tanstack/devtools': 0.6.8(@tanstack/devtools-ui@0.3.5(csstype@3.1.3)(solid-js@1.9.9))(csstype@3.1.3)(solid-js@1.9.9)
+ '@tanstack/devtools': 0.6.8(@tanstack/devtools-ui@0.4.0(csstype@3.1.3)(solid-js@1.9.9))(csstype@3.1.3)(solid-js@1.9.9)
'@types/react': 19.1.6
'@types/react-dom': 19.1.5(@types/react@19.1.6)
react: 19.1.0