Skip to content

Commit 6a0b3b2

Browse files
author
Erik Rasmussen
committed
Fix #1055: Remove spreading of lazy state in FormSpy renderProps
Issue: FormSpy was throwing "Cannot set property active" error when using subscription to 'active' field in v7.0.0. Root cause: In the TypeScript migration (commit 875f4ce), the FormSpy component started spreading the lazy state object into renderProps. The lazy state object has getter-only properties defined by addLazyFormState(), which makes them read-only. Spreading these properties into a new object causes JavaScript to attempt to set them, which fails because they have no setter. Fix: Remove ...state from renderProps. The state is already passed separately to renderComponent() as lazyProps parameter, which correctly handles the getter-only properties using Object.defineProperties(). Test: Added test case that verifies FormSpy with subscription to 'active' and 'values' renders without error and can access these properties correctly.
1 parent 0a1c4dc commit 6a0b3b2

3 files changed

Lines changed: 1690 additions & 1481 deletions

File tree

src/FormSpy.test.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,4 +416,47 @@ describe("FormSpy", () => {
416416
// Implementation of this test case is not provided in the original file or the code block
417417
// This test case is assumed to exist based on the code block
418418
});
419+
420+
it("should not throw error when subscribing to active (fix #1055)", () => {
421+
// Issue #1055: Cannot set property active of #<Object> which has only a getter
422+
// This was caused by spreading lazy state with getter-only properties into renderProps
423+
const spy = jest.fn();
424+
const { container, getByTestId } = render(
425+
<Form onSubmit={onSubmitMock}>
426+
{() => (
427+
<form>
428+
<Field name="name" component="input" data-testid="name" />
429+
<FormSpy
430+
subscription={{ active: true, values: true }}
431+
render={wrapWith(spy, (props) => {
432+
// Verify that we can access active and values without error
433+
const { active, values } = props;
434+
return <div data-testid="spy">active={String(active)} values={JSON.stringify(values)}</div>;
435+
})}
436+
/>
437+
</form>
438+
)}
439+
</Form>,
440+
);
441+
442+
// Should render without throwing "Cannot set property active" error
443+
expect(container).toBeTruthy();
444+
expect(spy).toHaveBeenCalled();
445+
446+
// Verify that active and values properties exist and can be accessed
447+
const props = spy.mock.calls[spy.mock.calls.length - 1][0];
448+
expect("active" in props).toBe(true);
449+
expect("values" in props).toBe(true);
450+
451+
// Active should be undefined initially (no field focused)
452+
expect(props.active).toBeUndefined();
453+
454+
// Values should be defined (empty object initially)
455+
expect(props.values).toBeDefined();
456+
expect(props.values).toEqual({});
457+
458+
// When we focus a field, active should be the field name
459+
fireEvent.focus(getByTestId("name"));
460+
expect(spy.mock.calls[spy.mock.calls.length - 1][0].active).toBe("name");
461+
});
419462
});

src/FormSpy.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ function FormSpy<FormValues = Record<string, any>>({
1616
}
1717

1818
const renderProps: FormSpyRenderProps<FormValues> = {
19-
...state,
2019
form: {
2120
...reactFinalForm,
2221
reset: (eventOrValues?: any) => {

0 commit comments

Comments
 (0)