antd 被包裹form元素点击清除图标后,数据未更新问题

3 篇文章 0 订阅
2 篇文章 0 订阅

bug复现

input/textarea 设置了allowClear属性为true,当点击清除图标后,form中关联的input/textarea 中的值未更新。

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, Button } from 'antd';


const Demo = () => {
  const [form] = Form.useForm()
  const onFinish = (values) => {
    console.log('Received values from form: ', values);
  };
  const onNumberChange = (e) => {
    onChange(e.target.value);
  };

  return (
    <Form
      form={form}
      name="customized_form_controls"
      layout="inline"
      onFinish={onFinish}
    >
      <Form.Item
        name="name"
        label="name"
      
      >
        <span>
          <Input
            allowClear="true"
            type="text"
            onChange={onNumberChange}
            style={{
              width: 100,
            }}
          />
      </span>
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<Demo />, document.getElementById('container'));

我们正常改变input/textarea 的值时,e.target.value的值和onFinish 时对应的值同步更新。当点击清除后,e.target.value值被清空。但是最终onFinish时获取到的值未更新。

原因分析:

主要是react合成事件带来的值更新不一致。

我们先来看下这个代码

import React, { useState } from "react";
import ReactDOM from "react-dom";

const Demo = () => {
  const inputOnchange = (e) => {
    console.log(1111111,e.target.value);
  };
  const spanOnchange = (e) => {
    console.log(2222222,e.target.value);
  };
  const divOnchange = (e) => {
    console.log(3333333,e.target.value);
  };
  
  return (
    <div onChange={divOnchange}>
      <span onChange={spanOnchange}>
        <input onChange={inputOnchange} />
      </span>
    </div>
  );
};

ReactDOM.render(<Demo />, document.getElementById("container"));

结果:

 

input/textarea 的onchange 事件是react合成事件 。

React合成事件一套机制:React并不是将click/change事件直接绑定在dom上面,而是采用事件冒泡的形式冒泡到document上面,然后React将事件封装给正式的函数处理运行和处理。

由此可见,由于react的合成机制,不管我们给input外层套上多少个dom元素,都可以捕获到值的变化并进行更新。这也就是为什么不管我们直接在Form组件中直接使用Input还是给Input外层套元素,我们在进行值的填充和删除时,Form均可以正确获得值的变化。

但是allowClear为什么不行呢?

我们来看一下antd源码关于这块的代码

 

从antd Input.tsx中可以看出,点击清除图标时执行了handleReset, handleReset中手动改变了一下当前input的值,并且调用resolveOnChange方法,该方法手动调用了一下Input上的onChange对应的方法,并没有触发事件冒泡机制,所以此时Input上的change方法执行,但是Input的父辈元素上的onChange方法并没有执行,导致获取的值没有更新。

解决方案:

手动触发父组件的onChange方法,实现事件的冒泡机制。这也是antd中对自定义form元素的解决方案。

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Form, Input, Button } from 'antd';


const CustomInput = ({ onChange }) => {

  const onNumberChange = (e) => {
    onChange(e.target.value);
  };

  

  return (
    <span>
      <Input
        allowClear="true"
        type="text"
        onChange={onNumberChange}
        style={{
          width: 100,
        }}
      />
    </span>
  );
};

const Demo = () => {
  const [form] = Form.useForm()
  const onFinish = (values) => {
    console.log('Received values from form: ', values);
  };


  return (
    <Form
      form={form}
      name="customized_form_controls"
      layout="inline"
      onFinish={onFinish}
    >
      <Form.Item
        name="name"
        label="name"
      
      >
        <CustomInput onChange={(e) => {console.log(e)}}/>
      </Form.Item>
      <Form.Item>
        <Button type="primary" htmlType="submit">
          Submit
        </Button>
      </Form.Item>
    </Form>
  );
};

ReactDOM.render(<Demo />, document.getElementById('container'));

希望可以帮到你们哦~~~ 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值