From e9184848e73a5e39fd2976826a7020328dba01ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=BA=8C=E8=B4=A7=E7=88=B1=E5=90=83=E7=99=BD=E8=90=9D?= =?UTF-8?q?=E5=8D=9C?= Date: Fri, 11 Aug 2023 16:00:31 +0800 Subject: [PATCH] Fix use watch trigger re-render twice in React 18 (#612) * chore: init * fix: useWatch trigger multiple render in React 18 * chore: ci --- .github/workflows/main.yml | 2 +- .gitignore | 3 ++- src/useWatch.ts | 11 ++++++++--- tests/useWatch.test.tsx | 3 +-- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5839a123..85650de4 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -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 diff --git a/.gitignore b/.gitignore index cee8485a..58f701c7 100644 --- a/.gitignore +++ b/.gitignore @@ -19,10 +19,11 @@ .DS_Store .vscode .idea +~* # umi .umi .umi-production .umi-test .env.local -.dumi/ \ No newline at end of file +.dumi/ diff --git a/src/useWatch.ts b/src/useWatch.ts index 23c41bc6..e5144083 100644 --- a/src/useWatch.ts +++ b/src/useWatch.ts @@ -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, @@ -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 extends Promise ? ValueType : never; type GetGeneric = ReturnPromise>; @@ -141,7 +141,12 @@ function useWatch(...args: [NamePath, FormInstance | WatchOptions] 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; }, diff --git a/tests/useWatch.test.tsx b/tests/useWatch.test.tsx index 16c1554d..2c035975 100644 --- a/tests/useWatch.test.tsx +++ b/tests/useWatch.test.tsx @@ -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 = () => {