Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,12 @@ const undecorate = decorator(form)
- [API](#api)
- [`createDecorator: (...calculations: Calculation[]) => Decorator`](#createdecorator-calculations-calculation--decorator)
- [Types](#types)
- [`Calculation: { field: FieldPattern, updates: Updates }`](#calculation--field-fieldpattern-updates-updates-)
- [`Calculation: { field: FieldPattern, isEqual?: (any, any) => boolean, updateOnPristine?: boolean, updates: Updates }`](#calculation--field-fieldpattern-isequal-any-any--boolean-updateonpristine-boolean-updates-updates-)
- [`FieldName: string`](#fieldname-string)
- [`FieldPattern: FieldName | RegExp`](#fieldpattern-fieldname--regexp)
- [`Updates: { [FieldName]: (value: any, allValues: Object, prevValues: Object) => any }`](#updates--fieldname-value-any-allvalues-object--any-)
- [`FieldPattern: FieldName | RegExp | (FieldName | RegExp)[]`](#fieldpattern-fieldname--regexp--fieldname--regexp)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix FieldPattern TOC signature mismatch.

Line 108 drops the array suffix in the displayed type ((FieldName | RegExp)), but Line 151 correctly documents (FieldName | RegExp)[]. Please align the TOC entry to avoid misleading API docs.

Suggested doc fix
-  - [`FieldPattern: FieldName | RegExp | (FieldName | RegExp)`](`#fieldpattern-fieldname--regexp--fieldname--regexp`)
+  - [`FieldPattern: FieldName | RegExp | (FieldName | RegExp)[]`](`#fieldpattern-fieldname--regexp--fieldname--regexp`)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
- [`FieldPattern: FieldName | RegExp | (FieldName | RegExp)[]`](#fieldpattern-fieldname--regexp--fieldname--regexp)
- [`FieldPattern: FieldName | RegExp | (FieldName | RegExp)[]`](`#fieldpattern-fieldname--regexp--fieldname--regexp`)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@README.md` at line 108, Update the README TOC entry for FieldPattern so the
displayed type matches the documented signature by including the array suffix;
change the link text that currently shows `(FieldName | RegExp)` to `(FieldName
| RegExp)[]` (the entry refers to FieldPattern and the anchor
`#fieldpattern-fieldname--regexp--fieldname--regexp`), ensuring the visible TOC
label and linked heading are consistent with the documented `(FieldName |
RegExp)[]` type in the body.

- [`Updates: UpdatesByName | UpdatesForAll`](#updates-updatesbyname--updatesforall)
- [`UpdatesByName: { [FieldName]: (value: any, allValues: Object, prevValues: Object) => Promise | any }`](#updatesbyname--fieldname-value-any-allvalues-object-prevvalues-object--promise--any-)
- [`UpdatesForAll: (value: any, field: string, allValues: Object, prevValues: Object) => Promise | { [FieldName]: any }`](#updatesforall-value-any-field-string-allvalues-object-prevvalues-object--promise---fieldname-any-)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand All @@ -126,10 +128,24 @@ A function that takes a set of calculations and returns a 🏁 Final Form

## Types

### `Calculation: { field: FieldPattern, isEqual?: (any, any) => boolean, updates: Updates }`
### `Calculation: { field: FieldPattern, isEqual?: (any, any) => boolean, updateOnPristine?: boolean, updates: Updates }`

A calculation to perform, with an optional `isEqual` predicate to determine if a value has really changed (defaults to `===`).

By default, calculations run when the decorator first subscribes, even if the form is still pristine. This is useful when calculated fields should be derived from `initialValues`. Set `updateOnPristine: false` to skip that initial calculation and only run after the source field becomes dirty:

```js
const decorator = createDecorator({
field: 'foo',
updateOnPristine: false,
updates: {
bar: fooValue => `${fooValue}bar`
}
})
```

`updateOnPristine: false` works with both object-style `updates` and function-style `updates`.

### `FieldName: string`

### `FieldPattern: FieldName | RegExp | (FieldName | RegExp)[]`
Expand Down
51 changes: 51 additions & 0 deletions src/decorator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,57 @@ describe('decorator', () => {
expect(bar.mock.calls[1][0].value).toBe('bazbar')
})

it('should not trigger update on initialValues if updateOnPristine is false, using an updates function', () => {
const form = createForm({
initialValues: { foo: 'test', bar: 'test' },
onSubmit: onSubmitMock
})
const spy = jest.fn()
const foo = jest.fn()
const bar = jest.fn()
form.subscribe(spy, { values: true })
form.registerField('foo', foo, { value: true })
form.registerField('bar', bar, { value: true })
const updates = jest.fn(fooValue => ({ bar: `${fooValue}bar` }))
const decorator = createDecorator({
field: 'foo',
updateOnPristine: false,
updates
})
const unsubscribe = decorator(form)
expect(typeof unsubscribe).toBe('function')

expect(updates).not.toHaveBeenCalled()
expect(spy).toHaveBeenCalledTimes(1)
expect(spy.mock.calls[0][0].values).toEqual({ foo: 'test', bar: 'test' })

expect(foo).toHaveBeenCalledTimes(1)
expect(foo.mock.calls[0][0].value).toBe('test')

expect(bar).toHaveBeenCalledTimes(1)
expect(bar.mock.calls[0][0].value).toBe('test')

// change foo (should trigger calculation on bar)
form.change('foo', 'baz')

expect(updates).toHaveBeenCalledTimes(1)
expect(updates).toHaveBeenCalledWith(
'baz',
'foo',
{ foo: 'baz', bar: 'test' },
{ foo: 'test', bar: 'test' }
)
expect(spy).toHaveBeenCalledTimes(3)
expect(spy.mock.calls[1][0].values).toEqual({ foo: 'baz', bar: 'test' })
expect(spy.mock.calls[2][0].values).toEqual({ foo: 'baz', bar: 'bazbar' })

expect(foo).toHaveBeenCalledTimes(2)
expect(foo.mock.calls[1][0].value).toBe('baz')

expect(bar).toHaveBeenCalledTimes(2)
expect(bar.mock.calls[1][0].value).toBe('bazbar')
})

it('should update one field when another changes', () => {
const form = createForm({ onSubmit: onSubmitMock })
const spy = jest.fn()
Expand Down
Loading