React - Input框绑定动态State和监听onChange事件,输入时失去焦点

React - Input框绑定动态State和监听onChange事件,输入时失去焦点

一. 案例复现

案例代码如下:

import React, { useState } from 'react';
import { Table, Input } from 'antd';
const Column = Table.Column;
const mockData = [{
  id: 1,
  name: 'test1',
  address: 'address1',
}, {
  id: 2,
  name: 'test1',
  address: 'address2',
}];
const index = () => {
  const [ data, setData ] = useState(mockData);

  const handleChange = (event: any, record: any, name: string) => {
    const currentVal = event.target.value;
    const { id } = record;
    const newData = data.map((item: any) => {
      return {
        ...item,
        [name]: item.id === id ? currentVal : item[name],
      };
    });
    setData(newData);
  };

  const AddressColumn = (props: any) => {
    const { record } = props;
    return <Input value={record.address} onChange={event => handleChange(event, record, 'address')} />;
  };

  return (
    <>
      <Table
        rowKey='id'
        style={{ width: '100%' }}
        dataSource={data}>
        <Column title='ID' key='id' dataIndex='id' />
        <Column title={'name'} key='name' dataIndex='name' render={(val: string, record: any) => {
          return <Input value={val} onChange={event => handleChange(event, record, 'name')} />;
        }} />
        <Column title={'address'} key='address' dataIndex='address' render={(val: string, record: any) => <AddressColumn record={record} />} />
      </Table>

    </>
  );
};

export default index;

页面如下
在这里插入图片描述
简单画了一个表格:

  1. name列可以修改,并且会动态修改对应的state
  2. address列同理,只不过用的是子组件AddressColumn渲染。

分别尝试在name列以及address列中更改Input框的内容,效果如下:
在这里插入图片描述

仔细观察可以发现:

  1. name列中的文本,可以随意输入,没有任何的限制。
  2. address列中的Input框内容一旦更改,就会失去焦点。

原因如下:

  1. 每次修改address列中的属性,动态修改了state的值。
  2. 组件重新渲染,导致AddressColumn组件也重新渲染。因此会生成一个新的Input框,导致失焦。

二. 解决方案

方式一:就如上述案例一样,采用name列式的写法,即将子组件的内容,提升到父组件中

<Column title={'address'} key='address' dataIndex='address' render={(val: string, record: any) => <AddressColumn record={record} />} />

改为
<Column title={'address'} key='address' dataIndex='address' render={(val: string, record: any) => {
  return <Input value={val} onChange={event => handleChange(event, record, 'address')} />;
}} />

方式二:使用useMemo钩子,封装一下子组件AddressColumn 避免重复渲染。

const AddressColumn = (props: any) => {
  const { record } = props;
  return <Input value={record.address} onChange={event => handleChange(event, record, 'address')} />;
};

改为
const AddressColumn = useMemo(() => (props: any) => {
  const { record } = props;
  return <Input value={record.address} onChange={event => handleChange(event, record, 'address')} />;
}, []);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zong_0915

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值