当前位置: 首页 > news >正文

useEffect 通过 form.getFieldValue(‘xxx‘) 监听 Form表单变化

场景

子组件中,某一个表格的数据需要依赖于上级组件的某一个表单元素值进行计算。

毫无疑问,首先想到的肯定是监听 form 表单中元素的值,使用 useEffect 监听表单的变化,当值发生变化时,重新计算渲染。

首先说下我的代码结构:

Form 表单是一个子组件,表格组件也是一个子组件,且是比较深的子组件(包含在tab标签页下)。如果说 Form子组件是一级子组件,那么表格组件就是一个四级子组件。

在这种多层嵌套下,如何把 form 数据传递给对应的表格子组件?

毫无疑问,选择使用:useContext

在顶层组件中通过 Form.useForm() 定义 Form 实例,管理数据状态,通过 <context.Provider value={}></context.Provider>传递,表单子组件和表格子组件都可进行接收。

不过在子组件监听代码写好后,却发现了一个比较尴尬的问题:表单元素的值发生了改变,但子组件的useEffect 却没能监听到。

// 子组件
import React, { useContext } from 'react'
import context from 'xxx/xxx'const { form } = useContext<any>(context)useEffect(() => {console.log('监听到了变化')// 下面是具体的逻辑
}, [form.getFiledValue('xx')])

注意:

当时令我困惑的是:当 Form 表单组件的某个表单元素值改变时,虽然子组件 useEffect 没有监听到变化,但通过表格子组件的输入框的 onBlur 事件,调用 form.getFiledValue('xx'),却可以拿到最新的值。

分析

需求终归还是要往下开发的,监听不了,那就想办法监听!

在项目中,我是使用了 const [form] = Form.useForm(); 来创建 Form 实例,管理表单数据状态,这也是函数式组件推荐的一种方式。

通过使用 useForm ,会让表单成为 非受控组件,不用通过 useState 创建state 来维护数据。

而且 ant 官网 里面也说了:使用这种方式与其他获取数据的方式的区别:

Form 仅会对变更的 Field 进行刷新,从而避免完整的组件刷新可能引发的性能问题,因而无法在 render 阶段通过 form.getFieldsValue 来实时获取字段值。



看到这里,其实已经很清楚了,因为 使用了 useForm,导致表单变成了 非受控组件,不能通过 useState 来创建 state 维护数据,只能通过 form.getFieldsValue() / form.setFieldsValue() 来获取及设置表单数据,ant design 官方文档也有介绍。所以在这种情况下, 使用 useEffect 监听不到 form 表单的变化。



换句话说:form.getFieldValue('xxx'); 并不是响应式的,由其取到的值,并不会触发 UI 更新,即:它不是一个 state。

不过,可能有人会问:我之前也使用过 useEffect 来监听 form.getFieldValue(‘xxx’),UI也能正常渲染啊,你这里是不是说错了?

答: 没有说错,我自己之前也有这样的疑问,也遇到过这类问题。



在实际项目中,一个 react 组件的 re-render 次数是不可控的, 特别是代码写的不那么规范的时候,所以,当看到 UI 更新的时候,或许是在新的 re-render 中被连带着更新了;又或许是项目代码中 Form组件既使用了 form = {form} 属性,又使用了 initialValues 属性。如下所示:

//
const [form] = Form.useForm();<Form initialValues={formData} form={form} ref={formRef}> </Form>

解决方案

方案1

ant design @4.20 版本推出了一个新特性:Form.useWatch,可以直接获取 form 中字段对应的值,应该是可以监听到的,具体用法可以参考官网,这里不多做赘述。

可是 4.2 版本后才支持,我的项目版本是 4.12.3,暂不支持这个hooks,部门领导也不让进行 ant 升级,所以就没有尝试这种写法。

而且使用这种方法,固然可以监听到,不过性能不是太好,不建议使用。因为它会触发整个组件的 re-render,当组件比较大且监听 input 实时输入时,性能消耗就很恐怖。

方案2

拒绝使用 Form.useForm(),使用 initialValues 属性,是表单变成一个可控组件,拥有 state,就可以正常监听。

不过对于我的项目代码来说,改动量太大,不划算。

方案3

使用 useState 额外定义个 state ,当表单元素值发生变化时,使用 setState(),然后将其值通过 context.Provider传递,在子组件监听。

方案4

使用 useReducer

useReduceruseState 都是用来存储和更新 state,相当于 useState 的升级版。

type 数量较多时,建议使用 useReducer

方案5

Ant Plus 5 的 Watch 组件

专门用于监听表单字段变化,并更新局部UI。(没尝试过)

总结

其实核心要点就一句话:Form 内置方法,不是响应式的(即不是一个state),由其设置或者获取的值,不会触发UI更新,只能对变更的field进行刷新。想要对其进行监听也很简单,将其变成一个state即可。

相关文章:

useEffect 通过 form.getFieldValue(‘xxx‘) 监听 Form表单变化

场景 子组件中&#xff0c;某一个表格的数据需要依赖于上级组件的某一个表单元素值进行计算。 毫无疑问&#xff0c;首先想到的肯定是监听 form 表单中元素的值&#xff0c;使用 useEffect 监听表单的变化&#xff0c;当值发生变化时&#xff0c;重新计算渲染。 首先说下我的…...

【晓龙oba出品 - 黑科技解题系列】- 最小操作次数使数组元素相等

思路 算法归根到底就是找规律的游戏&#xff0c;我们首先来看一个现象&#xff1a; 以数组nums [1,2,3,4,5]为例 当我们将数组排序后&#xff0c;可以知道最小值为1,最大值为5&#xff0c;此时我们需要四次运算可以使最小值与最大值相等&#xff1a; 第一次&#xff1a;2,3,4,…...

Activity的启动和结束

onCreate&#xff1a;创建活动。此时会把页面布局加载进内存&#xff0c;进入了初始状态。onStart&#xff1a;开启活动。此时会把活动页面显示在屏幕上&#xff0c;进入了就绪状态。onResume&#xff1a;恢复活动。此时活动页面进入活跃状态&#xff0c;能够与用户正常交互&am…...

利用业务逻辑+OB分布式特性优化SQL

最近某人社局核心数据库上了OB&#xff0c;经常出现性能问题 某人社与我司合作多年&#xff0c;非常信任我司在数据库的专业能力&#xff0c;邀请我司过去看看能否提供帮助 与OB驻场工程师合作&#xff0c;抓取了一天的TOP SQL&#xff0c;跑得慢的SQL有几十条(注意只是某一天的…...

哈希表

文章目录什么是哈希问题引入哈希函数直接定址法除留余数法 &#xff08;常用、重点&#xff09;哈希冲突哈希冲突的解决方法闭散列开散列unordered_map && unordered_set 封装实现哈希的应用位图布隆过滤器哈希经典面试题哈希切分位图应用布隆过滤器什么是哈希 在上一…...

基于Halcon的MLP(多层感知神经网络)分类器分类操作实例

一、介绍 人工神经网络(Artificial Neural Network,ANN)简称神经网络(Neural Network,NN)或类神经网络,是一种模仿生物神经网络的结构和功能的数学模型或计算模型,用于对函数进行估计或近似。 MLP神经网络是一种基于神经网络、动态的分类器。MLP分类器使用神经…...

VR全景博物馆,打造7*24小时的线上参访体验

导语&#xff1a;博物馆作为人们了解历史、文化和艺术的重要场所&#xff0c;现在可以通过VR全景技术来进行展览&#xff0c;让参观者身临其境地感受历史文化的魅力。本文将介绍博物馆VR全景的特点、优势&#xff0c;以及如何使用VR全景技术来丰富博物馆的展览和教育活动。什么…...

Go 数据类型

基础数据类型 类型长度&#xff08;字节&#xff09;默认值说明bool1falsebyte10uint8&#xff0c;取值范围[0,255]rune40Unicode Code Point&#xff0c;int32int,uint4或者8032位或64位操作系统int8,uint810-128~127&#xff0c;0-255int16,uint1620-32768~32767&#xff0c…...

Mybatis-Plus学透?一篇足够(持续更新中)

01、Mybatis-Plus入门 一、简介 MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。如果你想对自己的项目进行技术升级&#xff0c;不妨尝试将mybatis换成Mybati…...

船用燃料油市场调研报告-主要企业、市场规模、份额及发展趋势

船用燃料油市场报告主要研究&#xff1a;市场规模&#xff1a; 产能、产量、销售、产值、价格、成本、利润等行业分析&#xff1a;原材料、市场应用、产品种类、市场需求、市场供给&#xff0c;下游市场分析、供应链分析等竞争分析&#xff1a;主要企业情况、市场份额、并购、扩…...

python趣味编程-奥赛罗游戏

在上一期我们用Python实现了一个高速公路汽车游戏的游戏&#xff0c;这一期我们继续使用Python实现一个简单的奥赛罗游戏&#xff0c;让我们开始今天的旅程吧~ 在Python中使用Turtle实现的奥赛罗游戏 在Python中使用Turtle的简单奥赛罗游戏 是一个以 Python 为程序设计语言的项…...

经典卷积模型回顾13—ResNetXt实现图像分类(matlab)

ResNetXt是ResNet的变种&#xff0c;在ResNet基础上引入了"split-transform-merge"的思想&#xff0c;旨在进一步提升模型的性能和准确率。ResNetXt模型的核心思想是通过对输入进行分组&#xff0c;然后对每个分组进行不同的变换&#xff0c;最后再将变换后的结果合并…...

Spring学习——Maven进阶

分模块开发与设计 创建模块 书写模块代码 通过maven指令安装模块到本地仓库(install指令) 在pom.xml中导入坐标执行maven的install命令将模块安装到本地maven仓库 团队内部开发可以发布模块功能到团队内部可共享的仓库中&#xff08;私服) 依赖管理 依赖指当前项目运行所需…...

第23篇:基础知识-Java Switch Case

switch case 语句判断一个变量与一系列值中某个值是否相等,每个值称为一个分支。 switch case 语句语法格式如下: switch(expression){ case value : //语句 break; //可选 case value : //语句 break; //可选 //你可以有任意数量的…...

Go 实现多态和 参数的动态个数及动态类型

引子 go语言作为静态(编译期类型检测)强类型(手写代码进行类型转换)语言, 要想实现 动态语言的鸭子类型的调用方法,做到 一个入参是不同类型,还是有些麻烦的; 需求 希望写代码时像python一样的鸭子类型,不用管参数类型,都可以调用同一个方法;希望 入参像python一样 能够在 个…...

vue 指令

Vue 提供了很多指令&#xff0c;如&#xff1a;v-model, v-show&#xff0c;v-if等等&#xff0c;有利于应付开发时出现的各种情况。Vue 也提供了自定义指令&#xff0c;有利于开发者将某些通用性功能封装成一个指令&#xff0c;进行全局或局部注册。如&#xff1a;复制指令&am…...

APP违法违规收集使用个人信息合规评流程和范围

近期&#xff0c;工信部通报2023年第1批《侵害用户权益行为的APP通报》&#xff08;总第27批&#xff09;&#xff0c;共通报46款APP&#xff08;SDK&#xff09;&#xff0c;这些被责令限期整改的APP&#xff08;SDK&#xff09;&#xff0c;涉及的问题主要包括3个方面&#x…...

【力扣2379】 得到 K 个黑块的最少涂色次数(c++100%)

给你一个长度为 n 下标从 0 开始的字符串 blocks &#xff0c;blocks[i] 要么是 W 要么是 B &#xff0c;表示第 i 块的颜色。字符 W 和 B 分别表示白色和黑色。给你一个整数 k &#xff0c;表示想要 连续 黑色块的数目。每一次操作中&#xff0c;你可以选择一个白色块将它 涂成…...

[2.2.2]进程调度的时机、方式、切换与过程

文章目录第二章 进程管理进程调度的时机、方式、切换与过程&#xff08;一&#xff09;进程调度的时机&#xff08;二&#xff09;进程调度的方式&#xff08;三&#xff09;进程的切换与过程小结第二章 进程管理 进程调度的时机、方式、切换与过程 时机 什么时候需要进程调度…...

第24篇:Java包装类知识深度分析

目录 1、包装类背景 2、包装类的优点 3、包装类与基本类型关系 4、代码示例...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

IGP(Interior Gateway Protocol,内部网关协议)

IGP&#xff08;Interior Gateway Protocol&#xff0c;内部网关协议&#xff09; 是一种用于在一个自治系统&#xff08;AS&#xff09;内部传递路由信息的路由协议&#xff0c;主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

在四层代理中还原真实客户端ngx_stream_realip_module

一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡&#xff08;如 HAProxy、AWS NLB、阿里 SLB&#xff09;发起上游连接时&#xff0c;将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后&#xff0c;ngx_stream_realip_module 从中提取原始信息…...

剑指offer20_链表中环的入口节点

链表中环的入口节点 给定一个链表&#xff0c;若其中包含环&#xff0c;则输出环的入口节点。 若其中不包含环&#xff0c;则输出null。 数据范围 节点 val 值取值范围 [ 1 , 1000 ] [1,1000] [1,1000]。 节点 val 值各不相同。 链表长度 [ 0 , 500 ] [0,500] [0,500]。 …...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案

JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停​​ 1. ​​安全点(Safepoint)阻塞​​ ​​现象​​:JVM暂停但无GC日志,日志显示No GCs detected。​​原因​​:JVM等待所有线程进入安全点(如…...