Skip to content

Commit e918484

Browse files
authored
Fix use watch trigger re-render twice in React 18 (#612)
* chore: init * fix: useWatch trigger multiple render in React 18 * chore: ci
1 parent 476604d commit e918484

File tree

4 files changed

+12
-7
lines changed

4 files changed

+12
-7
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141

4242
- name: install
4343
if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
44-
run: npm ci
44+
run: npm i
4545

4646
lint:
4747
runs-on: ubuntu-latest

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,11 @@
1919
.DS_Store
2020
.vscode
2121
.idea
22+
~*
2223

2324
# umi
2425
.umi
2526
.umi-production
2627
.umi-test
2728
.env.local
28-
.dumi/
29+
.dumi/

src/useWatch.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import warning from 'rc-util/lib/warning';
2+
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
23
import FieldContext, { HOOK_MARK } from './FieldContext';
34
import type {
45
FormInstance,
@@ -8,9 +9,8 @@ import type {
89
Store,
910
WatchOptions,
1011
} from './interface';
11-
import { useState, useContext, useEffect, useRef, useMemo } from 'react';
12-
import { getNamePath, getValue } from './utils/valueUtil';
1312
import { isFormInstance } from './utils/typeUtil';
13+
import { getNamePath, getValue } from './utils/valueUtil';
1414

1515
type ReturnPromise<T> = T extends Promise<infer ValueType> ? ValueType : never;
1616
type GetGeneric<TForm extends FormInstance> = ReturnPromise<ReturnType<TForm['validateFields']>>;
@@ -141,7 +141,12 @@ function useWatch(...args: [NamePath, FormInstance | WatchOptions<FormInstance>]
141141
options.preserve ? getFieldsValue(true) : getFieldsValue(),
142142
namePathRef.current,
143143
);
144-
setValue(initialValue);
144+
145+
// React 18 has the bug that will queue update twice even the value is not changed
146+
// ref: https://github.com/facebook/react/issues/27213
147+
if (value !== initialValue) {
148+
setValue(initialValue);
149+
}
145150

146151
return cancelRegister;
147152
},

tests/useWatch.test.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,7 @@ describe('useWatch', () => {
227227
errorSpy.mockRestore();
228228
});
229229

230-
// FIXME: Not work in React 18
231-
it.skip('no more render time', async () => {
230+
it('no more render time', async () => {
232231
let renderTime = 0;
233232

234233
const Demo: React.FC = () => {

0 commit comments

Comments
 (0)