输入字段失去对每种字符类型的关注 - react

IT技术 reactjs redux
2021-04-01 06:25:34

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

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

分类.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 Table 中,我正在加载另一个组件 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>
    );

这个表头是我加载输入字段的地方,每当我输入这封信时,就会失去自动焦点。我怎么能修好呢?

3个回答

您通过创建嵌套组件(如Tbody. 这会在每次渲染时创建新组件(即使函数名称保持不变),并导致该组件重新安装

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

@AayushDahal 你需要按照反应规则重写整个事情.. 评论那部分不是解决方案,而只是一种确认重新安装会导致失去焦点的方法
2021-05-30 06:25:34
此外,将键设置为索引可能会导致重新安装。还有那些
2021-06-01 06:25:34
@Max 抱歉回复晚了。我明白你想说什么。但是,如果我评论那部分,我怎么能在输入字段上调用 ​​keyup 上的数据。
2021-06-11 06:25:34
@Max 你有任何资源链接吗?我可以遵循并正确添加列过滤器?如果你有一个这样的资源链接,你能分享一个吗?
2021-06-15 06:25:34

由于input组件失去焦点,这意味着它被重新渲染。它仅在输入组件之一更改类型或上层树更改时发生。在这种情况下,react 会完成重新渲染。

所以我猜在每个渲染上都定义了一个父组件 [ReduxTable, ReduxTableHeader]。就像你为 TBody 所做的那样。

在这种情况下,React 认为它是一种新型组件并破坏了以前的树并进行了完全重新渲染,这会导致性能滞后,并且在您的情况下会使输入失去焦点。

关于性能,您不应在函数内部定义组件。它使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>
);

看看这个帖子

我已经更新了代码并在那里展示了我如何向每个父组件添加密钥,但仍然是同样的问题。
2021-05-29 06:25:34
您可能必须在所有父元素上指定一个键属性
2021-06-04 06:25:34
向输入添加键并不能解决问题,您能否再看一次代码,可能是因为重新渲染了父元素?在每种类型上,它都会进行 api 调用,并且由于列表中的更新,整个表组件可能会重新渲染。
2021-06-16 06:25:34
看起来我已经在 ReduxTable 上添加了 key,你能检查一下上面的代码并请提到你在说什么 tr 吗?
2021-06-20 06:25:34
<tr> 也必须有一个键。同样在类别和 ReduxTable 中
2021-06-21 06:25:34