Skip to content

Commit 5b711e9

Browse files
committed
Fix initial render set by using setTimeout
1 parent 6b3c174 commit 5b711e9

File tree

2 files changed

+108
-56
lines changed

2 files changed

+108
-56
lines changed

packages/react-form-renderer/src/form-renderer/condition.js

Lines changed: 38 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -87,38 +87,45 @@ export const parseCondition = (condition, values) => {
8787
return negativeResult;
8888
};
8989

90-
const Condition = React.memo(({ condition, children, values }) => {
91-
const formOptions = useFormApi();
92-
const dirty = formOptions.getState().dirty;
93-
94-
const [lastSets, setSets] = React.useState([]);
95-
96-
const conditionResult = parseCondition(condition, values, formOptions);
97-
const setters = conditionResult.set ? [conditionResult.set] : conditionResult.sets;
98-
99-
useEffect(() => {
100-
if (!dirty) {
101-
setSets([]);
102-
}
103-
}, [dirty]);
104-
105-
useEffect(() => {
106-
if (setters && setters.length > 0 && (!dirty || !isEqual(setters, lastSets))) {
107-
setters.forEach((setter, index) => {
108-
if (setter && (!dirty || !isEqual(setter, lastSets[index]))) {
109-
formOptions.batch(() => {
110-
Object.entries(setter).forEach(([name, value]) => {
111-
formOptions.change(name, value);
90+
const Condition = React.memo(
91+
({ condition, children, values }) => {
92+
const formOptions = useFormApi();
93+
const dirty = formOptions.getState().dirty;
94+
95+
const [lastSets, setSets] = React.useState([]);
96+
const [initial, setInitial] = React.useState(true);
97+
98+
const conditionResult = parseCondition(condition, values, formOptions);
99+
const setters = conditionResult.set ? [conditionResult.set] : conditionResult.sets;
100+
101+
useEffect(() => {
102+
if (!dirty) {
103+
setInitial(true);
104+
}
105+
}, [dirty]);
106+
107+
useEffect(() => {
108+
if (setters && setters.length > 0 && (initial || !isEqual(setters, lastSets))) {
109+
setters.forEach((setter, index) => {
110+
if (setter && (initial || !isEqual(setter, lastSets[index]))) {
111+
setTimeout(() => {
112+
formOptions.batch(() => {
113+
Object.entries(setter).forEach(([name, value]) => {
114+
formOptions.change(name, value);
115+
});
116+
});
112117
});
113-
});
114-
}
115-
});
116-
setSets(setters);
117-
}
118-
}, [setters, dirty]);
119-
120-
return conditionResult.visible ? children : null;
121-
}, isEqual);
118+
}
119+
});
120+
setSets(setters);
121+
setInitial(false);
122+
}
123+
}, [setters, initial]);
124+
125+
return conditionResult.visible ? children : null;
126+
},
127+
(a, b) => isEqual(a.values, b.values) && isEqual(a.condition, b.condition)
128+
);
122129

123130
const conditionProps = {
124131
when: PropTypes.string,

packages/react-form-renderer/src/tests/form-renderer/condition.test.js

Lines changed: 70 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import React from 'react';
22
import { mount } from 'enzyme';
3+
import { act } from 'react-dom/test-utils';
34

45
import FormTemplate from '../../../../../__mocks__/mock-form-template';
56
import componentTypes from '../../../dist/cjs/component-types';
@@ -18,6 +19,8 @@ describe('condition test', () => {
1819
let wrapper;
1920

2021
beforeEach(() => {
22+
jest.useFakeTimers();
23+
2124
onSubmit = jest.fn();
2225

2326
initialProps = {
@@ -67,7 +70,7 @@ describe('condition test', () => {
6770
expect(wrapper.find('input')).toHaveLength(1);
6871
});
6972

70-
it('sets value when condition is fulfill', () => {
73+
it('sets value when condition is fulfill', async () => {
7174
schema = {
7275
fields: [
7376
{
@@ -90,24 +93,34 @@ describe('condition test', () => {
9093
]
9194
};
9295

93-
wrapper = mount(<FormRenderer {...initialProps} schema={schema} />);
96+
await act(async () => {
97+
wrapper = mount(<FormRenderer {...initialProps} schema={schema} />);
98+
});
99+
wrapper.update();
94100

95101
expect(wrapper.find('input')).toHaveLength(1);
96102

97-
wrapper.find('input').simulate('change', { target: { value: 'show' } });
103+
await act(async () => {
104+
wrapper.find('input').simulate('change', { target: { value: 'show' } });
105+
jest.advanceTimersByTime(1);
106+
});
98107
wrapper.update();
99108

100109
expect(wrapper.find('input')).toHaveLength(2);
101110

102-
wrapper.find('form').simulate('submit');
111+
await act(async () => {
112+
wrapper.find('form').simulate('submit');
113+
jest.advanceTimersByTime(1);
114+
});
115+
wrapper.update();
103116

104117
expect(onSubmit).toHaveBeenCalledWith({
105118
'field-1': 'show',
106119
'field-2': 'someValue'
107120
});
108121
});
109122

110-
it('sets value when condition is fulfill - initialValues', () => {
123+
it('sets value when condition is fulfill - initialValues', async () => {
111124
schema = {
112125
fields: [
113126
{
@@ -130,19 +143,26 @@ describe('condition test', () => {
130143
]
131144
};
132145

133-
wrapper = mount(<FormRenderer {...initialProps} schema={schema} initialValues={{ 'field-1': 'show' }} />);
146+
await act(async () => {
147+
wrapper = mount(<FormRenderer {...initialProps} schema={schema} initialValues={{ 'field-1': 'show' }} />);
148+
jest.advanceTimersByTime(1);
149+
});
150+
wrapper.update();
134151

135152
expect(wrapper.find('input')).toHaveLength(2);
136153

137-
wrapper.find('form').simulate('submit');
154+
await act(async () => {
155+
wrapper.find('form').simulate('submit');
156+
});
157+
wrapper.update();
138158

139159
expect(onSubmit).toHaveBeenCalledWith({
140160
'field-1': 'show',
141161
'field-2': 'someValue'
142162
});
143163
});
144164

145-
it('sets value when condition is fulfill on reset', () => {
165+
it('sets value when condition is fulfill on reset', async () => {
146166
schema = {
147167
fields: [
148168
{
@@ -165,41 +185,58 @@ describe('condition test', () => {
165185
]
166186
};
167187

168-
wrapper = mount(<FormRenderer {...initialProps} schema={schema} initialValues={{ 'field-1': 'show' }} />);
188+
await act(async () => {
189+
wrapper = mount(<FormRenderer {...initialProps} schema={schema} initialValues={{ 'field-1': 'show' }} />);
190+
jest.advanceTimersByTime(1);
191+
});
192+
wrapper.update();
169193

170194
expect(wrapper.find('input')).toHaveLength(2);
171195

172-
wrapper
173-
.find('input')
174-
.first()
175-
.simulate('change', { target: { value: 'dontshow' } });
196+
await act(async () => {
197+
wrapper
198+
.find('input')
199+
.first()
200+
.simulate('change', { target: { value: 'dontshow' } });
201+
jest.advanceTimersByTime(1);
202+
});
176203
wrapper.update();
177204

178205
expect(wrapper.find('input')).toHaveLength(1);
179206

180-
wrapper.find('form').simulate('submit');
207+
await act(async () => {
208+
wrapper.find('form').simulate('submit');
209+
});
210+
wrapper.update();
181211

182212
expect(onSubmit).toHaveBeenCalledWith({
183213
'field-1': 'dontshow',
184214
'field-2': 'someValue'
185215
});
186-
187-
//Reset
188-
wrapper
189-
.find('button')
190-
.at(1)
191-
.simulate('click');
216+
onSubmit.mockClear();
217+
218+
await act(async () => {
219+
//Reset
220+
wrapper
221+
.find('button')
222+
.at(1)
223+
.simulate('click');
224+
jest.advanceTimersByTime(1);
225+
});
192226
wrapper.update();
193227

194-
wrapper.find('form').simulate('submit');
228+
await act(async () => {
229+
wrapper.find('form').simulate('submit');
230+
});
231+
wrapper.update();
195232

196233
expect(onSubmit).toHaveBeenCalledWith({
197234
'field-1': 'show',
198235
'field-2': 'someValue'
199236
});
200237
});
201238

202-
it('sets value when condition is fulfill - sequence', () => {
239+
it('sets value when condition is fulfill - sequence', async () => {
203240
schema = {
204241
fields: [
205242
{
@@ -245,14 +282,22 @@ describe('condition test', () => {
245282
]
246283
};
247284

248-
wrapper = mount(<FormRenderer {...initialProps} schema={schema} />);
285+
await act(async () => {
286+
wrapper = mount(<FormRenderer {...initialProps} schema={schema} />);
287+
});
249288

250289
expect(wrapper.find('input')).toHaveLength(1);
251290

252-
wrapper.find('input').simulate('change', { target: { value: 'show' } });
291+
await act(async () => {
292+
wrapper.find('input').simulate('change', { target: { value: 'show' } });
293+
jest.advanceTimersByTime(1);
294+
});
253295
wrapper.update();
254296

255-
wrapper.find('form').simulate('submit');
297+
await act(async () => {
298+
wrapper.find('form').simulate('submit');
299+
});
300+
wrapper.update();
256301

257302
expect(onSubmit).toHaveBeenCalledWith({
258303
'field-1': 'show',

0 commit comments

Comments
 (0)