From 71a719d7c132089a383079b7fb5f37f0f9480737 Mon Sep 17 00:00:00 2001 From: oasis-cloud Date: Thu, 9 Jan 2025 16:09:53 +0800 Subject: [PATCH 1/6] feat(form): add useWatch --- src/packages/form/demo.taro.tsx | 5 ++ src/packages/form/demo.tsx | 5 ++ src/packages/form/demos/h5/demo8.tsx | 64 ++++++++++++++++++++++++++ src/packages/form/demos/taro/demo8.tsx | 64 ++++++++++++++++++++++++++ src/packages/form/doc.en-US.md | 12 ++++- src/packages/form/doc.md | 12 ++++- src/packages/form/doc.taro.md | 12 ++++- src/packages/form/doc.zh-TW.md | 12 ++++- src/packages/form/index.taro.ts | 4 +- src/packages/form/index.ts | 4 +- src/packages/form/useform.taro.ts | 40 +++++++++++++++- src/packages/form/useform.ts | 40 +++++++++++++++- 12 files changed, 266 insertions(+), 8 deletions(-) create mode 100644 src/packages/form/demos/h5/demo8.tsx create mode 100644 src/packages/form/demos/taro/demo8.tsx diff --git a/src/packages/form/demo.taro.tsx b/src/packages/form/demo.taro.tsx index 3881c4d845..0076b72f6a 100644 --- a/src/packages/form/demo.taro.tsx +++ b/src/packages/form/demo.taro.tsx @@ -9,6 +9,7 @@ import Demo4 from './demos/taro/demo4' import Demo5 from './demos/taro/demo5' import Demo6 from './demos/taro/demo6' import Demo7 from './demos/taro/demo7' +import Demo8 from './demos/taro/demo8' const FormDemo = () => { const [translated] = useTranslate({ @@ -20,6 +21,7 @@ const FormDemo = () => { title4: 'Form.useForm 对表单数据域进行交互。', title5: '表单类型', validateTrigger: '校验触发时机', + useWatch: 'useWatch', }, 'en-US': { basic: 'Basic Usage', @@ -29,6 +31,7 @@ const FormDemo = () => { title4: 'Interact with form data fields via Form.useForm', title5: 'Form Type', validateTrigger: 'Validate Trigger', + useWatch: 'useWatch', }, }) @@ -50,6 +53,8 @@ const FormDemo = () => {

{translated.title5}

+

{translated.useWatch}

+ ) diff --git a/src/packages/form/demo.tsx b/src/packages/form/demo.tsx index effa42d77a..dfbcccd246 100644 --- a/src/packages/form/demo.tsx +++ b/src/packages/form/demo.tsx @@ -7,6 +7,7 @@ import Demo4 from './demos/h5/demo4' import Demo5 from './demos/h5/demo5' import Demo6 from './demos/h5/demo6' import Demo7 from './demos/h5/demo7' +import Demo8 from './demos/h5/demo8' const FormDemo = () => { const [translated] = useTranslate({ @@ -18,6 +19,7 @@ const FormDemo = () => { title4: 'Form.useForm 对表单数据域进行交互。', title5: '表单类型', validateTrigger: '校验触发时机', + useWatch: 'useWatch', }, 'en-US': { basic: 'Basic Usage', @@ -27,6 +29,7 @@ const FormDemo = () => { title4: 'Interact with form data fields via Form.useForm', title5: 'Form Type', validateTrigger: 'Validate Trigger', + useWatch: 'useWatch', }, }) @@ -47,6 +50,8 @@ const FormDemo = () => {

{translated.title5}

+

{translated.useWatch}

+ ) diff --git a/src/packages/form/demos/h5/demo8.tsx b/src/packages/form/demos/h5/demo8.tsx new file mode 100644 index 0000000000..ddad724bd2 --- /dev/null +++ b/src/packages/form/demos/h5/demo8.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import { Button, Form, Input, Radio, Space } from '@nutui/nutui-react' + +type FieldType = { account?: string; loginMethod?: 'mobile' | 'email' } + +const Demo8 = () => { + const [form] = Form.useForm() + const account = Form.useWatch('account', form) + const loginMethod = Form.useWatch('loginMethod', form) + + return ( +
+
+
+ 你将使用 {loginMethod === 'mobile' ? '手机号' : '邮箱'} {account}{' '} + 登录 +
+ +
+ + } + > + + + + 手机号 + 邮箱 + + + + + <> + {loginMethod === 'mobile' && ( + + + + )} + {loginMethod === 'email' && ( + + + + )} + +
+ ) +} + +export default Demo8 diff --git a/src/packages/form/demos/taro/demo8.tsx b/src/packages/form/demos/taro/demo8.tsx new file mode 100644 index 0000000000..630ed331b2 --- /dev/null +++ b/src/packages/form/demos/taro/demo8.tsx @@ -0,0 +1,64 @@ +import React from 'react' +import { Button, Form, Input, Radio, Space } from '@nutui/nutui-react-taro' + +type FieldType = { account?: string; loginMethod?: 'mobile' | 'email' } + +const Demo8 = () => { + const [form] = Form.useForm() + const account = Form.useWatch('account', form) + const loginMethod = Form.useWatch('loginMethod', form) + + return ( +
+
+
+ 你将使用 {loginMethod === 'mobile' ? '手机号' : '邮箱'} {account}{' '} + 登录 +
+ +
+ + } + > + + + + 手机号 + 邮箱 + + + + + <> + {loginMethod === 'mobile' && ( + + + + )} + {loginMethod === 'email' && ( + + + + )} + +
+ ) +} + +export default Demo8 diff --git a/src/packages/form/doc.en-US.md b/src/packages/form/doc.en-US.md index ed414f760b..3116c15713 100644 --- a/src/packages/form/doc.en-US.md +++ b/src/packages/form/doc.en-US.md @@ -58,6 +58,14 @@ import { Form } from '@nutui/nutui-react' ::: +### useWatch + +:::demo + + + +::: + ### Form Type :::demo @@ -121,7 +129,7 @@ The rule validation process is based on [async-validator](https://github.com/yim ### FormInstance -Form.useForm() creates a Form instance, which is used to manage all data states. +`Form.useForm()` creates a Form instance, which is used to manage all data states. | Property | Description | Type | | --- | --- | --- | @@ -132,6 +140,8 @@ Form.useForm() creates a Form instance, which is used to manage all data states. | resetFields | Reset form prompt state | `() => void` | | submit | method to submit a form for validation | `Promise` | +`Form.useWath()`, this method will watch specified inputs and return their values. It is useful to render input value and for determining what to render by condition. + ## Theming ### CSS Variables diff --git a/src/packages/form/doc.md b/src/packages/form/doc.md index 2b176efff3..d9619d0048 100644 --- a/src/packages/form/doc.md +++ b/src/packages/form/doc.md @@ -58,6 +58,14 @@ import { Form } from '@nutui/nutui-react' ::: +### useWatch + +:::demo + + + +::: + ### 表单类型 :::demo @@ -120,7 +128,7 @@ import { Form } from '@nutui/nutui-react' ### FormInstance -Form.useForm()创建 Form 实例,用于管理所有数据状态。 +`Form.useForm()`创建 Form 实例,用于管理所有数据状态。 | 属性 | 说明 | 类型 | | --- | --- | --- | @@ -131,6 +139,8 @@ Form.useForm()创建 Form 实例,用于管理所有数据状态。 | resetFields | 重置表单提示状态 | `() => void` | | submit | 提交表单进行校验的方法 | `Promise` | +`Form.useWatch()`此方法将监视指定的输入并返回其值。它对于呈现输入值和确定根据条件呈现的内容很有用。 + ## 主题定制 ### 样式变量 diff --git a/src/packages/form/doc.taro.md b/src/packages/form/doc.taro.md index a6b01d1b5b..748db03665 100644 --- a/src/packages/form/doc.taro.md +++ b/src/packages/form/doc.taro.md @@ -58,6 +58,14 @@ import { Form } from '@nutui/nutui-react-taro' ::: +### useWatch + +:::demo + + + +::: + ### 表单类型 :::demo @@ -120,7 +128,7 @@ import { Form } from '@nutui/nutui-react-taro' ### FormInstance -Form.useForm()创建 Form 实例,用于管理所有数据状态。 +`Form.useForm()`创建 Form 实例,用于管理所有数据状态。 | 属性 | 说明 | 类型 | | --- | --- | --- | @@ -131,6 +139,8 @@ Form.useForm()创建 Form 实例,用于管理所有数据状态。 | resetFields | 重置表单提示状态 | `() => void` | | submit | 提交表单进行校验的方法 | `Promise` | +`Form.useWatch()`此方法将监视指定的输入并返回其值。它对于呈现输入值和确定根据条件呈现的内容很有用。 + ## 主题定制 ### 样式变量 diff --git a/src/packages/form/doc.zh-TW.md b/src/packages/form/doc.zh-TW.md index 8abf1361c3..8725a0a372 100644 --- a/src/packages/form/doc.zh-TW.md +++ b/src/packages/form/doc.zh-TW.md @@ -58,6 +58,14 @@ import { Form } from '@nutui/nutui-react' ::: +### useWatch + +:::demo + + + +::: + ### 表單類型 :::demo @@ -120,7 +128,7 @@ import { Form } from '@nutui/nutui-react' ### FormInstance -Form.useForm()創建 Form 實例,用於管理所有數據狀態。 +`Form.useForm()`創建 Form 實例,用於管理所有數據狀態。 | 屬性 | 說明 | 類型 | | --- | --- | --- | @@ -131,6 +139,8 @@ Form.useForm()創建 Form 實例,用於管理所有數據狀態。 | resetFields | 重置錶單提示狀態 | `() => void` | | submit | 提交錶單進行校驗的方法 | `Promise` | +`Form.useWatch()`此方法將監視指定的輸入並傳回其值。它對於呈現輸入值和確定根據條件呈現的內容很有用。 + ## 主題定制 ### 樣式變量 diff --git a/src/packages/form/index.taro.ts b/src/packages/form/index.taro.ts index 093d5218c8..fdfefdae35 100644 --- a/src/packages/form/index.taro.ts +++ b/src/packages/form/index.taro.ts @@ -2,7 +2,7 @@ import React from 'react' import { Form, FormProps } from './form.taro' import { FormItem } from '../formitem/formitem.taro' import { FormInstance } from './types' -import { useForm } from '@/packages/form/useform.taro' +import { useForm, useWatch } from '@/packages/form/useform.taro' export type { FormItemRuleWithoutValidator, @@ -17,11 +17,13 @@ type CompoundedComponent = React.ForwardRefExoticComponent< > & { Item: typeof FormItem useForm: typeof useForm + useWatch: typeof useWatch } const InnerForm = Form as CompoundedComponent InnerForm.Item = FormItem InnerForm.useForm = useForm +InnerForm.useWatch = useWatch export default InnerForm diff --git a/src/packages/form/index.ts b/src/packages/form/index.ts index 6563f8a986..748c374c25 100644 --- a/src/packages/form/index.ts +++ b/src/packages/form/index.ts @@ -2,7 +2,7 @@ import React from 'react' import { Form, FormProps } from './form' import { FormItem } from '../formitem/formitem' import { FormInstance } from './types' -import { useForm } from '@/packages/form/useform' +import { useForm, useWatch } from '@/packages/form/useform' export type { FormItemRuleWithoutValidator, @@ -17,11 +17,13 @@ type CompoundedComponent = React.ForwardRefExoticComponent< > & { Item: typeof FormItem useForm: typeof useForm + useWatch: typeof useWatch } const InnerForm = Form as CompoundedComponent InnerForm.Item = FormItem InnerForm.useForm = useForm +InnerForm.useWatch = useWatch export default InnerForm diff --git a/src/packages/form/useform.taro.ts b/src/packages/form/useform.taro.ts index 8559e5c5d7..6a177ede0b 100644 --- a/src/packages/form/useform.taro.ts +++ b/src/packages/form/useform.taro.ts @@ -1,4 +1,4 @@ -import { useRef } from 'react' +import { useRef, useState } from 'react' import Schema from 'async-validator' import { merge } from '@/utils/merge' import { @@ -11,6 +11,7 @@ import { export const SECRET = 'NUT_FORM_INTERNAL' type UpdateItem = { entity: FormFieldEntity; condition: any } +type WatchCallback = (value: Store, namePath: NamePath[]) => void /** * 用于存储表单的数据 @@ -90,6 +91,7 @@ class FormStore { if (init) { const nextStore = merge(initialValues, this.store) this.updateStore(nextStore) + this.notifyWatch() } } @@ -117,6 +119,7 @@ class FormStore { item.entity.onStoreChange('update') } }) + this.notifyWatch() } setFieldValue = (name: NamePath, value: T) => { @@ -124,6 +127,7 @@ class FormStore { [name]: value, } this.setFieldsValue(store) + this.notifyWatch([name]) } setCallback = (callback: Callbacks) => { @@ -234,6 +238,7 @@ class FormStore { store: this.store, fieldEntities: this.fieldEntities, registerUpdate: this.registerUpdate, + registerWatch: this.registerWatch, } } } @@ -251,6 +256,29 @@ class FormStore { getInternal: this.getInternal, } } + + private watchList: WatchCallback[] = [] + + private registerWatch = (callback) => { + this.watchList.push(callback) + + return () => { + this.watchList = this.watchList.filter((fn) => fn !== callback) + } + } + + private notifyWatch = (namePath: NamePath[] = []) => { + if (this.watchList.length) { + let allValues = this.getFieldsValue(namePath) + + if (!namePath || namePath.length === 0) { + allValues = this.getFieldsValue(true) + } + this.watchList.forEach((callback) => { + callback(allValues, namePath) + }) + } + } } export const useForm = (form?: FormInstance): [FormInstance] => { @@ -265,3 +293,13 @@ export const useForm = (form?: FormInstance): [FormInstance] => { } return [formRef.current as FormInstance] } + +export const useWatch = (path: NamePath, form: FormInstance) => { + const formInstance = form.getInternal(SECRET) + const [value, setValue] = useState() + formInstance.registerWatch((data: any, namePath: NamePath) => { + const value = data[path] + setValue(value) + }) + return value +} diff --git a/src/packages/form/useform.ts b/src/packages/form/useform.ts index 8559e5c5d7..6a177ede0b 100644 --- a/src/packages/form/useform.ts +++ b/src/packages/form/useform.ts @@ -1,4 +1,4 @@ -import { useRef } from 'react' +import { useRef, useState } from 'react' import Schema from 'async-validator' import { merge } from '@/utils/merge' import { @@ -11,6 +11,7 @@ import { export const SECRET = 'NUT_FORM_INTERNAL' type UpdateItem = { entity: FormFieldEntity; condition: any } +type WatchCallback = (value: Store, namePath: NamePath[]) => void /** * 用于存储表单的数据 @@ -90,6 +91,7 @@ class FormStore { if (init) { const nextStore = merge(initialValues, this.store) this.updateStore(nextStore) + this.notifyWatch() } } @@ -117,6 +119,7 @@ class FormStore { item.entity.onStoreChange('update') } }) + this.notifyWatch() } setFieldValue = (name: NamePath, value: T) => { @@ -124,6 +127,7 @@ class FormStore { [name]: value, } this.setFieldsValue(store) + this.notifyWatch([name]) } setCallback = (callback: Callbacks) => { @@ -234,6 +238,7 @@ class FormStore { store: this.store, fieldEntities: this.fieldEntities, registerUpdate: this.registerUpdate, + registerWatch: this.registerWatch, } } } @@ -251,6 +256,29 @@ class FormStore { getInternal: this.getInternal, } } + + private watchList: WatchCallback[] = [] + + private registerWatch = (callback) => { + this.watchList.push(callback) + + return () => { + this.watchList = this.watchList.filter((fn) => fn !== callback) + } + } + + private notifyWatch = (namePath: NamePath[] = []) => { + if (this.watchList.length) { + let allValues = this.getFieldsValue(namePath) + + if (!namePath || namePath.length === 0) { + allValues = this.getFieldsValue(true) + } + this.watchList.forEach((callback) => { + callback(allValues, namePath) + }) + } + } } export const useForm = (form?: FormInstance): [FormInstance] => { @@ -265,3 +293,13 @@ export const useForm = (form?: FormInstance): [FormInstance] => { } return [formRef.current as FormInstance] } + +export const useWatch = (path: NamePath, form: FormInstance) => { + const formInstance = form.getInternal(SECRET) + const [value, setValue] = useState() + formInstance.registerWatch((data: any, namePath: NamePath) => { + const value = data[path] + setValue(value) + }) + return value +} From 626e22e8a05f070df2c13c7a99173b095b837be2 Mon Sep 17 00:00:00 2001 From: oasis-cloud Date: Thu, 9 Jan 2025 18:07:25 +0800 Subject: [PATCH 2/6] fix: build error --- src/packages/form/demos/h5/demo8.tsx | 2 +- src/packages/form/demos/taro/demo8.tsx | 2 +- src/packages/form/useform.taro.ts | 2 +- src/packages/form/useform.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/packages/form/demos/h5/demo8.tsx b/src/packages/form/demos/h5/demo8.tsx index ddad724bd2..5e67f46de2 100644 --- a/src/packages/form/demos/h5/demo8.tsx +++ b/src/packages/form/demos/h5/demo8.tsx @@ -4,7 +4,7 @@ import { Button, Form, Input, Radio, Space } from '@nutui/nutui-react' type FieldType = { account?: string; loginMethod?: 'mobile' | 'email' } const Demo8 = () => { - const [form] = Form.useForm() + const [form] = Form.useForm() const account = Form.useWatch('account', form) const loginMethod = Form.useWatch('loginMethod', form) diff --git a/src/packages/form/demos/taro/demo8.tsx b/src/packages/form/demos/taro/demo8.tsx index 630ed331b2..ed443dc83a 100644 --- a/src/packages/form/demos/taro/demo8.tsx +++ b/src/packages/form/demos/taro/demo8.tsx @@ -4,7 +4,7 @@ import { Button, Form, Input, Radio, Space } from '@nutui/nutui-react-taro' type FieldType = { account?: string; loginMethod?: 'mobile' | 'email' } const Demo8 = () => { - const [form] = Form.useForm() + const [form] = Form.useForm() const account = Form.useWatch('account', form) const loginMethod = Form.useWatch('loginMethod', form) diff --git a/src/packages/form/useform.taro.ts b/src/packages/form/useform.taro.ts index 6a177ede0b..f2804d0a63 100644 --- a/src/packages/form/useform.taro.ts +++ b/src/packages/form/useform.taro.ts @@ -259,7 +259,7 @@ class FormStore { private watchList: WatchCallback[] = [] - private registerWatch = (callback) => { + private registerWatch = (callback: WatchCallback) => { this.watchList.push(callback) return () => { diff --git a/src/packages/form/useform.ts b/src/packages/form/useform.ts index 6a177ede0b..f2804d0a63 100644 --- a/src/packages/form/useform.ts +++ b/src/packages/form/useform.ts @@ -259,7 +259,7 @@ class FormStore { private watchList: WatchCallback[] = [] - private registerWatch = (callback) => { + private registerWatch = (callback: WatchCallback) => { this.watchList.push(callback) return () => { From 863e7597450c744b52d92a218b3d380084342db5 Mon Sep 17 00:00:00 2001 From: oasis-cloud Date: Thu, 9 Jan 2025 18:21:50 +0800 Subject: [PATCH 3/6] test: update case --- src/packages/form/__tests__/form.spec.tsx | 71 +++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/src/packages/form/__tests__/form.spec.tsx b/src/packages/form/__tests__/form.spec.tsx index 8a07b93e01..d5d3950501 100644 --- a/src/packages/form/__tests__/form.spec.tsx +++ b/src/packages/form/__tests__/form.spec.tsx @@ -2,6 +2,7 @@ import * as React from 'react' import { useEffect } from 'react' import { fireEvent, render, waitFor } from '@testing-library/react' import '@testing-library/jest-dom' +import { Button, Radio, Space } from '@nutui/nutui-react' import Form, { FormInstance } from '@/packages/form' import Input from '@/packages/input' @@ -312,3 +313,73 @@ test('no-style and render function', async () => { expect(relatedInput).toBeTruthy() }) }) + +test('useWatch', async () => { + const Demo = () => { + const [form] = Form.useForm() + const account = Form.useWatch('account', form) + const loginMethod = Form.useWatch('loginMethod', form) + return ( +
+
+
+ 你将使用 {loginMethod === 'mobile' ? '手机号' : '邮箱'}{' '} + {account} 登录 +
+ +
+ + } + > + + + + 手机号 + + 邮箱 + + + + + + <> + {loginMethod === 'mobile' && ( + + + + )} + {loginMethod === 'email' && ( + + + + )} + +
+ ) + } + + const { container } = render() + const clickTest = container.querySelector('.clickTest') + if (clickTest) { + fireEvent.click(clickTest) + const result = container.querySelector('.result') + expect(result).toHaveTextContent('你将使用 邮箱 123 登录') + } +}) From d5fe0dbdfd986ae996a0b5cc4869958e3416f2a1 Mon Sep 17 00:00:00 2001 From: oasis-cloud Date: Wed, 15 Jan 2025 13:43:48 +0800 Subject: [PATCH 4/6] =?UTF-8?q?fix(form):=20=E4=BF=AE=E5=A4=8D=20review=20?= =?UTF-8?q?=E6=84=8F=E8=A7=81=EF=BC=9B=E4=BB=A5=E5=8F=8A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BA=86=20registerField=20=E5=90=8E=EF=BC=8C=E5=9C=A8?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=94=80=E6=AF=81=E6=97=B6=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E9=BB=98=E8=AE=A4=E5=80=BC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/form/doc.en-US.md | 2 +- src/packages/form/useform.taro.ts | 31 +++++++++++++++++++++++-------- src/packages/form/useform.ts | 31 +++++++++++++++++++++++-------- 3 files changed, 47 insertions(+), 17 deletions(-) diff --git a/src/packages/form/doc.en-US.md b/src/packages/form/doc.en-US.md index 3116c15713..fa01e2fac5 100644 --- a/src/packages/form/doc.en-US.md +++ b/src/packages/form/doc.en-US.md @@ -140,7 +140,7 @@ The rule validation process is based on [async-validator](https://github.com/yim | resetFields | Reset form prompt state | `() => void` | | submit | method to submit a form for validation | `Promise` | -`Form.useWath()`, this method will watch specified inputs and return their values. It is useful to render input value and for determining what to render by condition. +`Form.useWatch()`, this method will watch specified inputs and return their values. It is useful to render input value and for determining what to render by condition. ## Theming diff --git a/src/packages/form/useform.taro.ts b/src/packages/form/useform.taro.ts index f2804d0a63..eb9eae78d2 100644 --- a/src/packages/form/useform.taro.ts +++ b/src/packages/form/useform.taro.ts @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import Schema from 'async-validator' import { merge } from '@/utils/merge' import { @@ -49,7 +49,12 @@ class FormStore { return () => { this.fieldEntities = this.fieldEntities.filter((item) => item !== field) if (this.store) { - delete this.store[field.props.name] + // 卸载后需要回复初始值 + const namePath = field.props.name + delete this.store[namePath] + this.updateStore( + merge(this.store, { [namePath]: this.initialValues[namePath] }) + ) } } } @@ -269,10 +274,11 @@ class FormStore { private notifyWatch = (namePath: NamePath[] = []) => { if (this.watchList.length) { - let allValues = this.getFieldsValue(namePath) - + let allValues if (!namePath || namePath.length === 0) { allValues = this.getFieldsValue(true) + } else { + allValues = this.getFieldsValue(namePath) } this.watchList.forEach((callback) => { callback(allValues, namePath) @@ -297,9 +303,18 @@ export const useForm = (form?: FormInstance): [FormInstance] => { export const useWatch = (path: NamePath, form: FormInstance) => { const formInstance = form.getInternal(SECRET) const [value, setValue] = useState() - formInstance.registerWatch((data: any, namePath: NamePath) => { - const value = data[path] - setValue(value) - }) + useEffect(() => { + const unsubscribe = formInstance.registerWatch( + (data: any, namePath: NamePath) => { + const value = data[path] + setValue(value) + } + ) + const initialValue = form.getFieldsValue(true) + if (value !== initialValue[path]) { + setValue(initialValue[path]) + } + return () => unsubscribe() + }, [form]) return value } diff --git a/src/packages/form/useform.ts b/src/packages/form/useform.ts index f2804d0a63..eb9eae78d2 100644 --- a/src/packages/form/useform.ts +++ b/src/packages/form/useform.ts @@ -1,4 +1,4 @@ -import { useRef, useState } from 'react' +import { useEffect, useRef, useState } from 'react' import Schema from 'async-validator' import { merge } from '@/utils/merge' import { @@ -49,7 +49,12 @@ class FormStore { return () => { this.fieldEntities = this.fieldEntities.filter((item) => item !== field) if (this.store) { - delete this.store[field.props.name] + // 卸载后需要回复初始值 + const namePath = field.props.name + delete this.store[namePath] + this.updateStore( + merge(this.store, { [namePath]: this.initialValues[namePath] }) + ) } } } @@ -269,10 +274,11 @@ class FormStore { private notifyWatch = (namePath: NamePath[] = []) => { if (this.watchList.length) { - let allValues = this.getFieldsValue(namePath) - + let allValues if (!namePath || namePath.length === 0) { allValues = this.getFieldsValue(true) + } else { + allValues = this.getFieldsValue(namePath) } this.watchList.forEach((callback) => { callback(allValues, namePath) @@ -297,9 +303,18 @@ export const useForm = (form?: FormInstance): [FormInstance] => { export const useWatch = (path: NamePath, form: FormInstance) => { const formInstance = form.getInternal(SECRET) const [value, setValue] = useState() - formInstance.registerWatch((data: any, namePath: NamePath) => { - const value = data[path] - setValue(value) - }) + useEffect(() => { + const unsubscribe = formInstance.registerWatch( + (data: any, namePath: NamePath) => { + const value = data[path] + setValue(value) + } + ) + const initialValue = form.getFieldsValue(true) + if (value !== initialValue[path]) { + setValue(initialValue[path]) + } + return () => unsubscribe() + }, [form]) return value } From 1b615f73459b14ef7bf8c40c9242c6a831782336 Mon Sep 17 00:00:00 2001 From: oasis-cloud Date: Thu, 16 Jan 2025 09:18:26 +0800 Subject: [PATCH 5/6] =?UTF-8?q?fix(form):=20=E4=BF=AE=E5=A4=8D=20review=20?= =?UTF-8?q?=E6=84=8F=E8=A7=81=EF=BC=9B=E4=BB=A5=E5=8F=8A=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E4=BA=86=20registerField=20=E5=90=8E=EF=BC=8C=E5=9C=A8?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E9=94=80=E6=AF=81=E6=97=B6=E5=BA=94=E8=AF=A5?= =?UTF-8?q?=E5=9B=9E=E5=A4=8D=E9=BB=98=E8=AE=A4=E5=80=BC=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/packages/form/demos/h5/demo8.tsx | 8 ++++---- src/packages/form/demos/taro/demo8.tsx | 8 ++++---- src/packages/form/useform.taro.ts | 10 ++-------- src/packages/form/useform.ts | 10 ++-------- 4 files changed, 12 insertions(+), 24 deletions(-) diff --git a/src/packages/form/demos/h5/demo8.tsx b/src/packages/form/demos/h5/demo8.tsx index 5e67f46de2..4cec12da48 100644 --- a/src/packages/form/demos/h5/demo8.tsx +++ b/src/packages/form/demos/h5/demo8.tsx @@ -26,8 +26,8 @@ const Demo8 = () => { marginBottom: '20px', }} > - 你将使用 {loginMethod === 'mobile' ? '手机号' : '邮箱'} {account}{' '} - 登录 + 你将使用{loginMethod === 'mobile' ? '手机号' : '电子邮箱'} + {account}登录