Skip to content

Commit cc0308b

Browse files
committed
fix(core, devtools): optimize event emissions
1 parent c3adef0 commit cc0308b

File tree

14 files changed

+253
-205
lines changed

14 files changed

+253
-205
lines changed

.changeset/fast-doors-hug.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@tanstack/form-devtools': patch
3+
'@tanstack/react-form': patch
4+
'@tanstack/form-core': patch
5+
---
6+
7+
Optimise Optimises event client emissions. Minor layout tweeks

examples/react/devtools/src/index.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ createRoot(document.getElementById('root')!).render(
1010
<StrictMode>
1111
<App />
1212

13-
<TanStackDevtools plugins={[FormDevtoolsPlugin()]} />
13+
<TanStackDevtools
14+
plugins={[FormDevtoolsPlugin()]}
15+
// eventBusConfig={{ debug: true }}
16+
/>
1417
</StrictMode>,
1518
)

packages/form-core/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
],
5353
"dependencies": {
5454
"@tanstack/devtools-event-client": "^0.2.5",
55+
"@tanstack/pacer": "^0.15.3",
5556
"@tanstack/store": "^0.7.5",
5657
"uuid": "^13.0.0"
5758
},

packages/form-core/src/EventClient.ts

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ type ExtractEventNames<T> = T extends `${string}:${infer EventName}`
99
export type BroadcastFormState = {
1010
id: string
1111
state: AnyFormState
12+
}
13+
14+
export type BroadcastFormApi = {
15+
id: string
16+
state: AnyFormState
1217
options: AnyFormOptions
1318
}
1419

@@ -33,29 +38,20 @@ export type BroadcastFormSubmissionState =
3338
successful: true
3439
}
3540

36-
export type BroadcastFormUnmounted = {
37-
id: string
38-
}
39-
40-
export type RequestFormState = {
41+
export type BroadcastFormId = {
4142
id: string
4243
}
4344

44-
export type RequestFormReset = {
45-
id: string
46-
}
45+
type EventMap = {
46+
'form-devtools:form-state': BroadcastFormState
47+
'form-devtools:form-api': BroadcastFormApi
48+
'form-devtools:form-submission': BroadcastFormSubmissionState
4749

48-
export type RequestFormForceReset = {
49-
id: string
50-
}
50+
'form-devtools:request-form-state': BroadcastFormId
51+
'form-devtools:request-form-reset': BroadcastFormId
52+
'form-devtools:request-form-force-submit': BroadcastFormId
5153

52-
type EventMap = {
53-
'form-devtools:form-state-change': BroadcastFormState
54-
'form-devtools:form-submission-state-change': BroadcastFormSubmissionState
55-
'form-devtools:form-unmounted': BroadcastFormUnmounted
56-
'form-devtools:request-form-state': RequestFormState
57-
'form-devtools:request-form-reset': RequestFormReset
58-
'form-devtools:request-form-force-submit': RequestFormForceReset
54+
'form-devtools:form-unmounted': BroadcastFormId
5955
}
6056

6157
export type EventClientEventMap = keyof EventMap

packages/form-core/src/FormApi.ts

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { Derived, Store, batch } from '@tanstack/store'
2+
import { throttle } from '@tanstack/pacer'
23
import { v4 as uuidv4 } from 'uuid'
34
import {
45
deleteBy,
@@ -21,11 +22,6 @@ import {
2122
} from './standardSchemaValidator'
2223
import { defaultFieldMeta, metaHelper } from './metaHelper'
2324
import { formEventClient } from './EventClient'
24-
import type {
25-
RequestFormForceReset,
26-
RequestFormReset,
27-
RequestFormState,
28-
} from './EventClient'
2925
import type { ValidationLogicFn } from './ValidationLogic'
3026
import type {
3127
StandardSchemaV1,
@@ -1296,17 +1292,26 @@ export class FormApi<
12961292

12971293
this.update(opts || {})
12981294

1295+
const debouncedDevtoolState = throttle(
1296+
(state: AnyFormState) =>
1297+
formEventClient.emit('form-state', {
1298+
id: this._formId,
1299+
state: state,
1300+
}),
1301+
{
1302+
wait: 300,
1303+
},
1304+
)
1305+
1306+
// devtool broadcasts
12991307
this.store.subscribe(() => {
1300-
formEventClient.emit('form-state-change', {
1301-
id: this._formId,
1302-
state: this.store.state,
1303-
options: this.options,
1304-
})
1308+
debouncedDevtoolState(this.store.state)
13051309
})
13061310

1311+
// devtool requests
13071312
formEventClient.on('request-form-state', (e) => {
13081313
if (e.payload.id === this._formId) {
1309-
formEventClient.emit('form-state-change', {
1314+
formEventClient.emit('form-api', {
13101315
id: this._formId,
13111316
state: this.store.state,
13121317
options: this.options,
@@ -1376,7 +1381,7 @@ export class FormApi<
13761381
const { onMount } = this.options.validators || {}
13771382

13781383
// broadcast form state for devtools on mounting
1379-
formEventClient.emit('form-state-change', {
1384+
formEventClient.emit('form-api', {
13801385
id: this._formId,
13811386
state: this.store.state,
13821387
options: this.options,
@@ -1454,6 +1459,12 @@ export class FormApi<
14541459
),
14551460
)
14561461
})
1462+
1463+
formEventClient.emit('form-api', {
1464+
id: this._formId,
1465+
state: this.store.state,
1466+
options: this.options,
1467+
})
14571468
}
14581469

14591470
/**
@@ -2035,7 +2046,7 @@ export class FormApi<
20352046
meta: submitMetaArg,
20362047
})
20372048

2038-
formEventClient.emit('form-submission-state-change', {
2049+
formEventClient.emit('form-submission', {
20392050
id: this._formId,
20402051
submissionAttempt: this.state.submissionAttempts,
20412052
successful: false,
@@ -2059,7 +2070,7 @@ export class FormApi<
20592070
meta: submitMetaArg,
20602071
})
20612072

2062-
formEventClient.emit('form-submission-state-change', {
2073+
formEventClient.emit('form-submission', {
20632074
id: this._formId,
20642075
submissionAttempt: this.state.submissionAttempts,
20652076
successful: false,
@@ -2098,7 +2109,7 @@ export class FormApi<
20982109
isSubmitSuccessful: true, // Set isSubmitSuccessful to true on successful submission
20992110
}))
21002111

2101-
formEventClient.emit('form-submission-state-change', {
2112+
formEventClient.emit('form-submission', {
21022113
id: this._formId,
21032114
submissionAttempt: this.state.submissionAttempts,
21042115
successful: true,
@@ -2112,7 +2123,7 @@ export class FormApi<
21122123
isSubmitSuccessful: false, // Ensure isSubmitSuccessful is false if an error occurs
21132124
}))
21142125

2115-
formEventClient.emit('form-submission-state-change', {
2126+
formEventClient.emit('form-submission', {
21162127
id: this._formId,
21172128
submissionAttempt: this.state.submissionAttempts,
21182129
successful: false,

packages/form-devtools/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"src"
5353
],
5454
"dependencies": {
55-
"@tanstack/devtools-ui": "^0.3.5",
55+
"@tanstack/devtools-ui": "^0.4.1",
5656
"@tanstack/form-core": "workspace:*",
5757
"clsx": "^2.1.1",
5858
"dayjs": "^1.11.13",

packages/form-devtools/src/components/ActionButtons.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { Accessor } from 'solid-js'
66
import type { DevtoolsFormState } from '../contexts/eventClientContext'
77

88
type ActionButtonsProps = {
9-
selectedInstance: Accessor<DevtoolsFormState | null>
9+
selectedInstance: Accessor<DevtoolsFormState | null | undefined>
1010
}
1111

1212
export function ActionButtons(props: ActionButtonsProps) {

0 commit comments

Comments
 (0)