Skip to content

Commit e7f776a

Browse files
authored
fix: onFieldsChange in strict mode (#228)
* revert: register in constructor * fix: Initial field pathed value * fix: Logic of double rendered
1 parent dd18a0f commit e7f776a

File tree

5 files changed

+55
-3
lines changed

5 files changed

+55
-3
lines changed

src/Field.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,16 +133,23 @@ class Field extends React.Component<InternalFieldProps, FieldState> implements F
133133
// Register on init
134134
if (props.fieldContext) {
135135
const { getInternalHooks }: InternalFormInstance = props.fieldContext;
136-
const { registerField } = getInternalHooks(HOOK_MARK);
137-
this.cancelRegisterFunc = registerField(this);
136+
const { initEntityValue } = getInternalHooks(HOOK_MARK);
137+
initEntityValue(this);
138138
}
139139
}
140140

141141
public componentDidMount() {
142-
const { shouldUpdate } = this.props;
142+
const { shouldUpdate, fieldContext } = this.props;
143143

144144
this.mounted = true;
145145

146+
// Register on init
147+
if (fieldContext) {
148+
const { getInternalHooks }: InternalFormInstance = fieldContext;
149+
const { registerField } = getInternalHooks(HOOK_MARK);
150+
this.cancelRegisterFunc = registerField(this);
151+
}
152+
146153
// One more render for component in case fields not ready
147154
if (shouldUpdate === true) {
148155
this.reRender();

src/FieldContext.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ const Context = React.createContext<InternalFormInstance>({
2929

3030
return {
3131
dispatch: warningFunc,
32+
initEntityValue: warningFunc,
3233
registerField: warningFunc,
3334
useSubscribe: warningFunc,
3435
setInitialValues: warningFunc,

src/interface.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ export interface Callbacks<Values = any> {
181181

182182
export interface InternalHooks {
183183
dispatch: (action: ReducerAction) => void;
184+
initEntityValue: (entity: FieldEntity) => void;
184185
registerField: (entity: FieldEntity) => () => void;
185186
useSubscribe: (subscribable: boolean) => void;
186187
setInitialValues: (values: Store, init: boolean) => void;

src/useForm.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ export class FormStore {
100100

101101
return {
102102
dispatch: this.dispatch,
103+
initEntityValue: this.initEntityValue,
103104
registerField: this.registerField,
104105
useSubscribe: this.useSubscribe,
105106
setInitialValues: this.setInitialValues,
@@ -504,6 +505,22 @@ export class FormStore {
504505
};
505506

506507
// =========================== Observer ===========================
508+
/**
509+
* This only trigger when a field is on constructor to avoid we get initialValue too late
510+
*/
511+
private initEntityValue = (entity: FieldEntity) => {
512+
const { initialValue } = entity.props;
513+
514+
if (initialValue !== undefined) {
515+
const namePath = entity.getNamePath();
516+
const prevValue = getValue(this.store, namePath);
517+
518+
if (prevValue === undefined) {
519+
this.store = setValue(this.store, namePath, initialValue);
520+
}
521+
}
522+
};
523+
507524
private registerField = (entity: FieldEntity) => {
508525
this.fieldEntities.push(entity);
509526

tests/strict.test.tsx

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import { mount } from 'enzyme';
3+
import Form from '../src';
4+
import InfoField, { Input } from './common/InfoField';
5+
import { changeValue } from './common';
6+
7+
describe('Form.ReactStrict', () => {
8+
it('should not register twice', async () => {
9+
const onFieldsChange = jest.fn();
10+
11+
const wrapper = mount(
12+
<React.StrictMode>
13+
<Form name="testForm" onFieldsChange={onFieldsChange}>
14+
<InfoField name="input">
15+
<Input />
16+
</InfoField>
17+
</Form>
18+
</React.StrictMode>,
19+
);
20+
21+
await changeValue(wrapper, 'bamboo');
22+
23+
expect(onFieldsChange).toHaveBeenCalledTimes(1);
24+
expect(onFieldsChange.mock.calls[0][1]).toHaveLength(1);
25+
});
26+
});

0 commit comments

Comments
 (0)