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

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

FFmpeg 低延迟同屏方案

引言 在实时互动需求激增的当下&#xff0c;无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作&#xff0c;还是游戏直播的画面实时传输&#xff0c;低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架&#xff0c;凭借其灵活的编解码、数据…...

visual studio 2022更改主题为深色

visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中&#xff0c;选择 环境 -> 常规 &#xff0c;将其中的颜色主题改成深色 点击确定&#xff0c;更改完成...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命

在华东塑料包装行业面临限塑令深度调整的背景下&#xff0c;江苏艾立泰以一场跨国资源接力的创新实践&#xff0c;重新定义了绿色供应链的边界。 跨国回收网络&#xff1a;废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点&#xff0c;将海外废弃包装箱通过标准…...

Nuxt.js 中的路由配置详解

Nuxt.js 通过其内置的路由系统简化了应用的路由配置&#xff0c;使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

selenium学习实战【Python爬虫】

selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...

使用Spring AI和MCP协议构建图片搜索服务

目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式&#xff08;本地调用&#xff09; SSE模式&#xff08;远程调用&#xff09; 4. 注册工具提…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...