Skip to content

Commit 3bf7096

Browse files
authored
perf(core): memoize prepareFormState (#7498)
* perf(core): memoize prepareFormState * refactor(core): update root form state options * fix(core): fix memoization bugs * test(core): finish tests for every form option * fix(core): fix stale `fieldGroupState` memo result * refactor(core): return named function for readability * docs(core): add JSDoc for `getId` * refactor(core): mark sub-functions of `PrepareFormState` as internal * fix: don't use symbols in weakmaps for firefox compat
1 parent 4a50023 commit 3bf7096

File tree

19 files changed

+2434
-1049
lines changed

19 files changed

+2434
-1049
lines changed

packages/sanity/playwright-ct/tests/formBuilder/utils/TestForm.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,8 @@ export function TestForm(props: TestFormProps) {
157157
validateStaticDocument(document, workspace, (result) => setValidation(result))
158158
}, [document, workspace])
159159

160-
const formState = useFormState(schemaType, {
160+
const formState = useFormState({
161+
schemaType,
161162
focusPath,
162163
collapsedPaths,
163164
collapsedFieldSets,
@@ -166,7 +167,7 @@ export function TestForm(props: TestFormProps) {
166167
openPath,
167168
presence: presenceFromProps,
168169
validation,
169-
value: document,
170+
documentValue: document,
170171
})
171172

172173
const formStateRef = useRef(formState)

packages/sanity/src/core/form/store/__tests__/collapsible.test.ts

+13-7
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import {describe, expect, it, test} from '@jest/globals'
1+
import {beforeEach, describe, expect, it, test} from '@jest/globals'
22
import {Schema} from '@sanity/schema'
33
import {type ObjectSchemaType, type Path} from '@sanity/types'
44

55
import {pathToString} from '../../../field'
6-
import {prepareFormState} from '../formState'
6+
import {createPrepareFormState, type PrepareFormState} from '../formState'
77
import {type FieldMember, type ObjectFormNode} from '../types'
88
import {isObjectFormNode} from '../types/asserters'
99
import {DEFAULT_PROPS} from './shared'
@@ -81,6 +81,12 @@ function getBookType(fieldOptions: {
8181
}).get('book')
8282
}
8383

84+
let prepareFormState!: PrepareFormState
85+
86+
beforeEach(() => {
87+
prepareFormState = createPrepareFormState()
88+
})
89+
8490
test("doesn't make primitive fields collapsed even if they are configured to be", () => {
8591
// Note: the schema validation should possibly enforce this
8692
// Note2: We might want to support making all kinds of fields collapsible, even primitive fields
@@ -93,7 +99,7 @@ test("doesn't make primitive fields collapsed even if they are configured to be"
9399
const result = prepareFormState({
94100
...DEFAULT_PROPS,
95101
schemaType: bookType,
96-
document: {_id: 'foo', _type: 'book'},
102+
documentValue: {_id: 'foo', _type: 'book'},
97103
})
98104

99105
expect(result).not.toBe(null)
@@ -121,7 +127,7 @@ describe('collapsible object fields', () => {
121127
const result = prepareFormState({
122128
...DEFAULT_PROPS,
123129
schemaType: bookType,
124-
document: {_id: 'foo', _type: 'book'},
130+
documentValue: {_id: 'foo', _type: 'book'},
125131
})
126132

127133
expect(result).not.toBe(null)
@@ -141,7 +147,7 @@ describe('collapsible object fields', () => {
141147
const result = prepareFormState({
142148
...DEFAULT_PROPS,
143149
schemaType: bookType,
144-
document: {_id: 'foo', _type: 'book'},
150+
documentValue: {_id: 'foo', _type: 'book'},
145151
})
146152

147153
expect(result).not.toBe(null)
@@ -160,7 +166,7 @@ describe('collapsible object fields', () => {
160166
const result = prepareFormState({
161167
...DEFAULT_PROPS,
162168
schemaType: bookType,
163-
document: {_id: 'foo', _type: 'book'},
169+
value: {_id: 'foo', _type: 'book'},
164170
})
165171

166172
expect(result).not.toBe(null)
@@ -184,7 +190,7 @@ describe('collapsible object fields', () => {
184190
const result = prepareFormState({
185191
...DEFAULT_PROPS,
186192
schemaType: bookType,
187-
document: {_id: 'foo', _type: 'book'},
193+
documentValue: {_id: 'foo', _type: 'book'},
188194
})
189195

190196
expect(result).not.toBe(null)

packages/sanity/src/core/form/store/__tests__/equality.test.ts

+11-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import {expect, test} from '@jest/globals'
1+
import {beforeEach, expect, test} from '@jest/globals'
22
import {Schema} from '@sanity/schema'
33
import {type ConditionalProperty} from '@sanity/types'
44

5-
import {prepareFormState} from '../formState'
5+
import {createPrepareFormState, type PrepareFormState} from '../formState'
66
import {DEFAULT_PROPS} from './shared'
77

88
function getBookType(properties: {
@@ -73,20 +73,26 @@ function getBookType(properties: {
7373
}).get('book')
7474
}
7575

76+
let prepareFormState!: PrepareFormState
77+
78+
beforeEach(() => {
79+
prepareFormState = createPrepareFormState()
80+
})
81+
7682
test('it doesnt return new object equalities given the same input', () => {
77-
const document = {_id: 'test', _type: 'foo'}
83+
const documentValue = {_id: 'test', _type: 'foo'}
7884
const bookType = getBookType({})
7985

8086
const state1 = prepareFormState({
8187
...DEFAULT_PROPS,
8288
schemaType: bookType,
83-
document,
89+
documentValue,
8490
})
8591

8692
const state2 = prepareFormState({
8793
...DEFAULT_PROPS,
8894
schemaType: bookType,
89-
document,
95+
documentValue,
9096
})
9197
expect(state1).not.toBe(null)
9298
expect(state2).not.toBe(null)

0 commit comments

Comments
 (0)