Skip to content

Commit

Permalink
Fix use watch trigger re-render twice in React 18 (#612)
Browse files Browse the repository at this point in the history
* chore: init

* fix: useWatch trigger multiple render in React 18

* chore: ci
  • Loading branch information
zombieJ authored Aug 11, 2023
1 parent 476604d commit e918484
Show file tree
Hide file tree
Showing 4 changed files with 12 additions and 7 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ jobs:

- name: install
if: steps.node_modules_cache_id.outputs.cache-hit != 'true'
run: npm ci
run: npm i

lint:
runs-on: ubuntu-latest
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,11 @@
.DS_Store
.vscode
.idea
~*

# umi
.umi
.umi-production
.umi-test
.env.local
.dumi/
.dumi/
11 changes: 8 additions & 3 deletions src/useWatch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import warning from 'rc-util/lib/warning';
import { useContext, useEffect, useMemo, useRef, useState } from 'react';
import FieldContext, { HOOK_MARK } from './FieldContext';
import type {
FormInstance,
Expand All @@ -8,9 +9,8 @@ import type {
Store,
WatchOptions,
} from './interface';
import { useState, useContext, useEffect, useRef, useMemo } from 'react';
import { getNamePath, getValue } from './utils/valueUtil';
import { isFormInstance } from './utils/typeUtil';
import { getNamePath, getValue } from './utils/valueUtil';

type ReturnPromise<T> = T extends Promise<infer ValueType> ? ValueType : never;
type GetGeneric<TForm extends FormInstance> = ReturnPromise<ReturnType<TForm['validateFields']>>;
Expand Down Expand Up @@ -141,7 +141,12 @@ function useWatch(...args: [NamePath, FormInstance | WatchOptions<FormInstance>]
options.preserve ? getFieldsValue(true) : getFieldsValue(),
namePathRef.current,
);
setValue(initialValue);

// React 18 has the bug that will queue update twice even the value is not changed
// ref: https://github.com/facebook/react/issues/27213
if (value !== initialValue) {
setValue(initialValue);
}

return cancelRegister;
},
Expand Down
3 changes: 1 addition & 2 deletions tests/useWatch.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -227,8 +227,7 @@ describe('useWatch', () => {
errorSpy.mockRestore();
});

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

const Demo: React.FC = () => {
Expand Down

1 comment on commit e918484

@vercel
Copy link

@vercel vercel bot commented on e918484 Aug 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.