反应输入在功能组件的数据表中失去焦点
React input losing focus in Datatable in functional component
在我的数据表中,当我在输入中键入任何字符并在组件内定义组件时,输入失去焦点。但是,当我将组件直接放在数据表中时,它就可以工作了。我知道第一种情况不起作用,因为每次我键入一个字符时组件都会重新呈现。但是为什么第二种情况有效呢?以及如何在不将代码直接放入数据表的情况下让第一个案例工作。
Codesandbox:https://codesandbox.io/s/test-2p30w
不工作(第一个案例)
import Datatable from "react-table";
import { useState } from "react";
const Test = () => {
const [first, setFirst] = useState("");
const [second, setSecond] = useState("");
const Field1 = () => (
<input
defaultValue={first}
onChange={(e) => setFirst(e.currentTarget.value)}
/>
);
const Field2 = () => (
<input
defaultValue={second}
onChange={(e) => setSecond(e.currentTarget.value)}
/>
);
return (
<Datatable
noText
pageSize={1}
showPagination={false}
data={[{ userName: "asdas", email: "asdsad" }]}
columns={[
{
Header: "www",
accessor: "userName",
Cell: <Field1 />
},
{
Header: "Email",
accessor: "email",
Cell: <Field2 />
}
]}
/>
);
};
export default Test;
工作(第二种情况)
import Datatable from "react-table";
import { useState } from "react";
const Test = () => {
const [first, setFirst] = useState("");
const [second, setSecond] = useState("");
return (
<Datatable
noText
pageSize={1}
showPagination={false}
data={[{ userName: "asdas", email: "asdsad" }]}
columns={[
{
Header: "www",
accessor: "userName",
Cell: (
<input
defaultValue={first}
onChange={(e) => setFirst(e.currentTarget.value)}
/>
)
},
{
Header: "Email",
accessor: "email",
Cell: (
<input
defaultValue={second}
onChange={(e) => setSecond(e.currentTarget.value)}
/>
)
}
]}
/>
);
};
export default Test;
焦点丢失是因为您在 Test
的正文中声明了 Field1
和 Field2
组件,这意味着每次渲染都会创建新的组件,任何状态都将是丢失。您可以通过将 Field1
和 Field2
定义提升到顶级范围并将局部变量引用替换为 props 来修复它(这将使它们相等,因此您可以只使用一个 Field
):
const Field = ({ defaultValue, onChange }) => (
<input defaultValue={defaultValue} onChange={onChange} />
);
const Test = () => {
const [first, setFirst] = useState("");
const [second, setSecond] = useState("");
return (
<Datatable
noText
pageSize={1}
showPagination={false}
data={[{ userName: "asdas", email: "asdsad" }]}
columns={[
{
Header: "www",
accessor: "userName",
Cell: (
<Field
defaultValue={first}
onChange={(e) => setFirst(e.currentTarget.value)}
/>
)
},
{
Header: "Email",
accessor: "email",
Cell: (
<Field
defaultValue={second}
onChange={(e) => setSecond(e.currentTarget.value)}
/>
)
}
]}
/>
);
};
在我的数据表中,当我在输入中键入任何字符并在组件内定义组件时,输入失去焦点。但是,当我将组件直接放在数据表中时,它就可以工作了。我知道第一种情况不起作用,因为每次我键入一个字符时组件都会重新呈现。但是为什么第二种情况有效呢?以及如何在不将代码直接放入数据表的情况下让第一个案例工作。
Codesandbox:https://codesandbox.io/s/test-2p30w
不工作(第一个案例)
import Datatable from "react-table";
import { useState } from "react";
const Test = () => {
const [first, setFirst] = useState("");
const [second, setSecond] = useState("");
const Field1 = () => (
<input
defaultValue={first}
onChange={(e) => setFirst(e.currentTarget.value)}
/>
);
const Field2 = () => (
<input
defaultValue={second}
onChange={(e) => setSecond(e.currentTarget.value)}
/>
);
return (
<Datatable
noText
pageSize={1}
showPagination={false}
data={[{ userName: "asdas", email: "asdsad" }]}
columns={[
{
Header: "www",
accessor: "userName",
Cell: <Field1 />
},
{
Header: "Email",
accessor: "email",
Cell: <Field2 />
}
]}
/>
);
};
export default Test;
工作(第二种情况)
import Datatable from "react-table";
import { useState } from "react";
const Test = () => {
const [first, setFirst] = useState("");
const [second, setSecond] = useState("");
return (
<Datatable
noText
pageSize={1}
showPagination={false}
data={[{ userName: "asdas", email: "asdsad" }]}
columns={[
{
Header: "www",
accessor: "userName",
Cell: (
<input
defaultValue={first}
onChange={(e) => setFirst(e.currentTarget.value)}
/>
)
},
{
Header: "Email",
accessor: "email",
Cell: (
<input
defaultValue={second}
onChange={(e) => setSecond(e.currentTarget.value)}
/>
)
}
]}
/>
);
};
export default Test;
焦点丢失是因为您在 Test
的正文中声明了 Field1
和 Field2
组件,这意味着每次渲染都会创建新的组件,任何状态都将是丢失。您可以通过将 Field1
和 Field2
定义提升到顶级范围并将局部变量引用替换为 props 来修复它(这将使它们相等,因此您可以只使用一个 Field
):
const Field = ({ defaultValue, onChange }) => (
<input defaultValue={defaultValue} onChange={onChange} />
);
const Test = () => {
const [first, setFirst] = useState("");
const [second, setSecond] = useState("");
return (
<Datatable
noText
pageSize={1}
showPagination={false}
data={[{ userName: "asdas", email: "asdsad" }]}
columns={[
{
Header: "www",
accessor: "userName",
Cell: (
<Field
defaultValue={first}
onChange={(e) => setFirst(e.currentTarget.value)}
/>
)
},
{
Header: "Email",
accessor: "email",
Cell: (
<Field
defaultValue={second}
onChange={(e) => setSecond(e.currentTarget.value)}
/>
)
}
]}
/>
);
};