输入字段失去对每个字符类型的关注-反应



我试图在表的标题上添加列过滤器,但每次在字段上输入后,它都会失去焦点。

我的主要组件:在这里,我已经初始化了一个本地状态:searchColArrfetchData中使用的所有其他状态都是redux状态,它们正在使用useSelectror初始化

Category.jsx

const [searchColArr, setSearchColArr] = useState({
name: "",
});
//all these default value are either local state or redux state
function fetchData(
newPage = page,
newPerPage = perPage,
newOrder = order,
newDir = dir,
newSearchColArr = searchColArr,
newSearch = search
) {
dispatch(
listCategory(
newPage,
newPerPage,
newOrder,
newDir,
newSearchColArr,
newSearch
)
);
}
const headerRow = React.useMemo(
() => [
{
header: "Name",
name: "name",
filter: true,
sort: true,
},
{
header: "Action",
name: "id",
filter: false,
sort: false,
},
],
[]
);
const TBody = () => {
return (
<tbody key="tbody">
{list &&
list.map((row, i) => (
<tr key={row.id}>
<td>{row.name}</td>
<td>
<ActionColumn id={row.id} />
</td>
</tr>
))}
</tbody>
);
};
const handleColSearch = ({ currentTarget: input }) => {
setSearchColArr({
...searchColArr,
[input.name]: input.value,
});
};
useEffect(() => {
fetchData();
}, [searchColArr]);
return (
<div className="row">
<div className="col-md-12">
{/* REDUX TABLE STARTS */}
<ReduxTable
key="redux-table"
isLoading={isLoading}
headerRow={headerRow}
list={list}
page={page}
perPage={perPage}
order={order}
dir={dir}
total={total}
totalPage={totalPage}
searchColArr={searchColArr}
handlePageLengthChange={handlePageLengthChange}
handlePageChange={handlePageChange}
handleColSearch={handleColSearch}
TBody={TBody}
/>
{/* REDUX TABLE ENDS */}
</div>
</div>
);

并且,在Redux表中,我正在加载另一个组件ReduxTableHeader

ReduxTable

const ReduxTable = ({
isLoading,
headerRow,
list,
page,
perPage,
order,
dir,
total,
totalPage,
searchColArr,
handlePageLengthChange,
handlePageChange,
handleColSearch,
TBody,
}) => {
return (
<div className="card-box">
{/* TABLE HEADER AND BODY just looping thorugh list*/}
<table
id="basicTable"
className="table table-bordered action-table table-striped table-hover mb-0"
>
{/* ReduxTableHeader */}
<ReduxTableHeader
key="redux-table-header"
headerRow={headerRow}
searchColArr={searchColArr}
handleColSearch={handleColSearch}
/>
<TBody />
</table>

</div>
);
};

ReduxTableHeader

return (
<thead key="thead">
<tr>
//list of header name
</tr>
<tr key="filter-row">
{headerRow &&
headerRow.map((v, i) => (
<th key={v.name}>
{v.filter ? (
<input
type="search"
className="form-control form-control-sm d-inline-block"
placeholder=""
aria-controls="datatable"
name={v.name}
value={searchColArr[v.name] || ""}
onChange={handleColSearch}
autoComplete="off"
key={"index" + i}
/>
) : (
""
)}
</th>
))}
</tr>
</thead>
);

这个表头是我加载输入字段的地方,每当我键入这个字母时,就会失去自动聚焦。我该怎么修?

您创建像Tbody这样的嵌套组件违反了React的规则。这会在每次渲染时创建新组件(即使函数名称保持不变(,并导致该组件重新装载

在99.999%的情况下,您的输入会因为其父组件之一的重新安装而失去焦点,从而在每次键入内容时创建一个新的组件树(和新的输入元素(。您可能正在做与组件树中的Tbody相同的事情,并且每次触发fetchData时,您的整个Category组件都会重新装载。为了确认,您可以注释掉触发fetchDatauseEffect

由于input组件失去焦点,这意味着它被重新绘制。只有当输入组件中的一个更改了类型或上层树更改时,才会发生这种情况。在这种情况下,react会完成重新发送。

因此,我想在每个渲染中都定义了一个父组件[ReuxTable,ReduxTableHeader]。就像你为TBody做的那样。

在这种情况下,React认为这是一种新类型的组件,并销毁以前的树,并进行完全的重新发布,这会导致性能滞后,在您的情况下会使输入失去焦点。

关于性能,您不应该在函数内部定义组件。这让反应变得愚蠢。

若要防止这种情况,您需要确保所有输入的父组件都是在Render函数之外定义的。在这种情况下,在功能组件之外。

请检查我的代码沙箱链接,它演示了2个案例。

  1. 当您尝试编辑第一行输入时,它不会失去焦点
  2. 当您尝试编辑TBody中的其他输入时,将失去焦点也许你们也有同样的问题

https://codesandbox.io/s/react-playground-rvikz?file=/src/App.js:567-572

为您的输入指定一个唯一的键将导致React重用它,而不是重新绘制它。因此,在设置视图状态后,它应该保持焦点。

return (
<thead>
<tr>
/list of header name
</tr>
<tr>
{headerRow &&
headerRow.map((v, i) => (
<th key={v.name}>
{v.filter ? (
<input
type="search"
className="form-control form-control-sm d-inline-block"
placeholder=""
aria-controls="datatable"
name={v.name}
value={searchColArr[v.name] || ""}
onChange={handleColSearch}
autoComplete="off"
key={'input' + i}
/>
) : (
""
)}
</th>
))}
</tr>
</thead>
);

看看这个后

最新更新