当前位置: 首页 > 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、代码示例...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

Qt Http Server模块功能及架构

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

爬虫基础学习day2

# 爬虫设计领域 工商&#xff1a;企查查、天眼查短视频&#xff1a;抖音、快手、西瓜 ---> 飞瓜电商&#xff1a;京东、淘宝、聚美优品、亚马逊 ---> 分析店铺经营决策标题、排名航空&#xff1a;抓取所有航空公司价格 ---> 去哪儿自媒体&#xff1a;采集自媒体数据进…...

Yolov8 目标检测蒸馏学习记录

yolov8系列模型蒸馏基本流程&#xff0c;代码下载&#xff1a;这里本人提交了一个demo:djdll/Yolov8_Distillation: Yolov8轻量化_蒸馏代码实现 在轻量化模型设计中&#xff0c;**知识蒸馏&#xff08;Knowledge Distillation&#xff09;**被广泛应用&#xff0c;作为提升模型…...

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

STM32HAL库USART源代码解析及应用

STM32HAL库USART源代码解析 前言STM32CubeIDE配置串口USART和UART的选择使用模式参数设置GPIO配置DMA配置中断配置硬件流控制使能生成代码解析和使用方法串口初始化__UART_HandleTypeDef结构体浅析HAL库代码实际使用方法使用轮询方式发送使用轮询方式接收使用中断方式发送使用中…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...

Unity中的transform.up

2025年6月8日&#xff0c;周日下午 在Unity中&#xff0c;transform.up是Transform组件的一个属性&#xff0c;表示游戏对象在世界空间中的“上”方向&#xff08;Y轴正方向&#xff09;&#xff0c;且会随对象旋转动态变化。以下是关键点解析&#xff1a; 基本定义 transfor…...