背景
隔壁 zym 同事遇到了一个问题,在编辑表格时,每输入一个字符后都会失去焦点,需要重新点击聚焦后才能继续输入,如图:
原因
归根结底,是关于 key 的问题。
原先的代码中,components 在 render 中,然而在每次 setState 后都会触发 render,因此相当于每次 components 都是一个新变量、新组件。
import "./styles.css";
import React from "react";
import { Table, Input } from "antd";
import "antd/dist/antd.css";
export default class App extends React.Component {
state = {
tableInput: "",
dataSource: [
{
name: "blueju",
password: "blueju",
type: 1
}
]
};
handleInputChange = (e, text, index) => {
const dataSource = JSON.parse(JSON.stringify(this.state.dataSource));
dataSource[index].name = e.target.value;
this.setState({
dataSource
});
};
render() {
const components = {
table(props) {
return <table>{props.children}</table>;
}
};
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Table dataSource={this.state.dataSource} components={components}>
<Table.Column
dataIndex="name"
title="name"
render={(text, record, index) => {
if (record.type === 1) {
return (
<Input
// key={index}
value={this.state.tableInput}
onChange={(e) => {
// this.handleInputChange(e, text, index);
this.setState({
tableInput: e.target.value
});
}}
/>
);
}
if (record.type === 2) {
return text;
}
}}
/>
</Table>
<Input.TextArea
value={JSON.stringify(this.state.dataSource, null, 2)}
autoSize
/>
</div>
);
}
}
修改后:
将 components 提到组件外,当然如果不需要被其他组件共享,你也可以提到组件内部。
import "./styles.css";
import React from "react";
import { Table, Input } from "antd";
import "antd/dist/antd.css";
const components = {
table(props) {
return <table>{props.children}</table>;
}
};
export default class App extends React.Component {
state = {
tableInput: "",
dataSource: [
{
name: "blueju",
password: "blueju",
type: 1
}
]
};
handleInputChange = (e, text, index) => {
const dataSource = JSON.parse(JSON.stringify(this.state.dataSource));
dataSource[index].name = e.target.value;
this.setState({
dataSource
});
};
render() {
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Table dataSource={this.state.dataSource} components={components}>
<Table.Column
dataIndex="name"
title="name"
render={(text, record, index) => {
if (record.type === 1) {
return (
<Input
// key={index}
value={this.state.tableInput}
onChange={(e) => {
// this.handleInputChange(e, text, index);
this.setState({
tableInput: e.target.value
});
}}
/>
);
}
if (record.type === 2) {
return text;
}
}}
/>
</Table>
<Input.TextArea
value={JSON.stringify(this.state.dataSource, null, 2)}
autoSize
/>
</div>
);
}
}
修改后效果图:
Github
https://github.com/blueju/BlogCodeSandBox/tree/master/input-onblur-in-antd-table