Skip to content

Commit 79b34ad

Browse files
committed
fix(core, devtools): optimize event emissions
1 parent e877dfb commit 79b34ad

File tree

14 files changed

+1520
-3755
lines changed

14 files changed

+1520
-3755
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: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,8 @@
5252
],
5353
"dependencies": {
5454
"@tanstack/devtools-event-client": "^0.3.2",
55-
"@tanstack/store": "^0.7.7"
55+
"@tanstack/store": "^0.7.7",
56+
"@tanstack/pacer": "^0.15.3"
5657
},
5758
"devDependencies": {
5859
"arktype": "^2.1.22",

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 & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Derived, Store, batch } from '@tanstack/store'
2-
2+
import { throttle } from '@tanstack/pacer'
33
import {
44
deleteBy,
55
determineFormLevelErrorSourceAndValue,
@@ -22,11 +22,6 @@ import {
2222
} from './standardSchemaValidator'
2323
import { defaultFieldMeta, metaHelper } from './metaHelper'
2424
import { formEventClient } from './EventClient'
25-
import type {
26-
RequestFormForceReset,
27-
RequestFormReset,
28-
RequestFormState,
29-
} from './EventClient'
3025
import type { ValidationLogicFn } from './ValidationLogic'
3126
import type {
3227
StandardSchemaV1,
@@ -1297,17 +1292,26 @@ export class FormApi<
12971292

12981293
this.update(opts || {})
12991294

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
13001307
this.store.subscribe(() => {
1301-
formEventClient.emit('form-state-change', {
1302-
id: this._formId,
1303-
state: this.store.state,
1304-
options: this.options,
1305-
})
1308+
debouncedDevtoolState(this.store.state)
13061309
})
13071310

1311+
// devtool requests
13081312
formEventClient.on('request-form-state', (e) => {
13091313
if (e.payload.id === this._formId) {
1310-
formEventClient.emit('form-state-change', {
1314+
formEventClient.emit('form-api', {
13111315
id: this._formId,
13121316
state: this.store.state,
13131317
options: this.options,
@@ -1377,7 +1381,7 @@ export class FormApi<
13771381
const { onMount } = this.options.validators || {}
13781382

13791383
// broadcast form state for devtools on mounting
1380-
formEventClient.emit('form-state-change', {
1384+
formEventClient.emit('form-api', {
13811385
id: this._formId,
13821386
state: this.store.state,
13831387
options: this.options,
@@ -1455,6 +1459,12 @@ export class FormApi<
14551459
),
14561460
)
14571461
})
1462+
1463+
formEventClient.emit('form-api', {
1464+
id: this._formId,
1465+
state: this.store.state,
1466+
options: this.options,
1467+
})
14581468
}
14591469

14601470
/**
@@ -2053,7 +2063,7 @@ export class FormApi<
20532063
meta: submitMetaArg,
20542064
})
20552065

2056-
formEventClient.emit('form-submission-state-change', {
2066+
formEventClient.emit('form-submission', {
20572067
id: this._formId,
20582068
submissionAttempt: this.state.submissionAttempts,
20592069
successful: false,
@@ -2077,7 +2087,7 @@ export class FormApi<
20772087
meta: submitMetaArg,
20782088
})
20792089

2080-
formEventClient.emit('form-submission-state-change', {
2090+
formEventClient.emit('form-submission', {
20812091
id: this._formId,
20822092
submissionAttempt: this.state.submissionAttempts,
20832093
successful: false,
@@ -2116,7 +2126,7 @@ export class FormApi<
21162126
isSubmitSuccessful: true, // Set isSubmitSuccessful to true on successful submission
21172127
}))
21182128

2119-
formEventClient.emit('form-submission-state-change', {
2129+
formEventClient.emit('form-submission', {
21202130
id: this._formId,
21212131
submissionAttempt: this.state.submissionAttempts,
21222132
successful: true,
@@ -2130,7 +2140,7 @@ export class FormApi<
21302140
isSubmitSuccessful: false, // Ensure isSubmitSuccessful is false if an error occurs
21312141
}))
21322142

2133-
formEventClient.emit('form-submission-state-change', {
2143+
formEventClient.emit('form-submission', {
21342144
id: this._formId,
21352145
submissionAttempt: this.state.submissionAttempts,
21362146
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.18",

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)