Skip to content

Commit e283978

Browse files
authored
fix: No more render times (#415)
* test: test driven * fix: no more render times
1 parent f27229f commit e283978

File tree

2 files changed

+63
-3
lines changed

2 files changed

+63
-3
lines changed

src/useWatch.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import { getNamePath, getValue } from './utils/valueUtil';
88

99
const useWatch = <ValueType = Store>(dependencies: NamePath = [], form?: FormInstance) => {
1010
const [value, setValue] = useState<ValueType>();
11+
const valueCacheRef = useRef<ValueType>();
12+
valueCacheRef.current = value;
1113

1214
const fieldContext = useContext(FieldContext);
1315
const formInstance = (form as InternalFormInstance) || fieldContext;
@@ -37,7 +39,9 @@ const useWatch = <ValueType = Store>(dependencies: NamePath = [], form?: FormIns
3739

3840
const cancelRegister = registerWatch(store => {
3941
const newValue = getValue(store, namePathRef.current);
40-
setValue(newValue);
42+
if (valueCacheRef.current !== newValue) {
43+
setValue(newValue);
44+
}
4145
});
4246

4347
// TODO: We can improve this perf in future
@@ -46,10 +50,10 @@ const useWatch = <ValueType = Store>(dependencies: NamePath = [], form?: FormIns
4650

4751
return cancelRegister;
4852
},
49-
/* eslint-disable react-hooks/exhaustive-deps */
53+
5054
// We do not need re-register since namePath content is the same
55+
// eslint-disable-next-line react-hooks/exhaustive-deps
5156
[],
52-
/* eslint-enable */
5357
);
5458

5559
return value;

tests/useWatch.test.tsx

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,4 +219,60 @@ describe('useWatch', () => {
219219
'Warning: useWatch requires a form instance since it can not auto detect from context.',
220220
);
221221
});
222+
223+
it('no more render time', () => {
224+
let renderTime = 0;
225+
226+
const Demo = () => {
227+
const [form] = Form.useForm();
228+
const name = Form.useWatch<string>('name', form);
229+
230+
renderTime += 1;
231+
232+
return (
233+
<Form form={form}>
234+
<Field name="name">
235+
<Input />
236+
</Field>
237+
<Field name="age">
238+
<Input />
239+
</Field>
240+
<div className="value">{name}</div>
241+
</Form>
242+
);
243+
};
244+
245+
const wrapper = mount(<Demo />);
246+
expect(renderTime).toEqual(1);
247+
248+
wrapper
249+
.find('input')
250+
.first()
251+
.simulate('change', {
252+
target: {
253+
value: 'bamboo',
254+
},
255+
});
256+
expect(renderTime).toEqual(2);
257+
258+
wrapper
259+
.find('input')
260+
.last()
261+
.simulate('change', {
262+
target: {
263+
value: '123',
264+
},
265+
});
266+
expect(renderTime).toEqual(2);
267+
268+
wrapper
269+
.find('input')
270+
.last()
271+
.simulate('change', {
272+
target: {
273+
value: '123456',
274+
},
275+
});
276+
expect(renderTime).toEqual(2);
277+
});
222278
});

0 commit comments

Comments
 (0)