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

Posted

技术标签:

【中文标题】输入字段失去对每个字符类型的关注 - 反应【英文标题】:Input field losing focus on each character type - react 【发布时间】:2021-08-02 12:56:42 【问题描述】:

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

我的主要组件:在这里,我初始化了一个本地状态: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 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>
    );

这个表头是我加载输入字段的地方,每当我在这个字母上输入时,都会失去自动焦点。我该如何解决?

【问题讨论】:

每次调用 handleColSearch 后,您的组件可能会重新渲染。如果没有更多背景信息,将很难进一步诊断。 你想看哪个文件,请告诉我。 见***.com/questions/22573494/… 如果可能,请添加代码沙箱链接。 【参考方案1】:

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

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

【讨论】:

将键设置为索引也会导致重新挂载。还有那些 @Max 抱歉回复晚了。我明白你想说什么。但是,如果我评论了那部分,我怎么能在输入字段上调用 ​​keyup 上的数据。 @AayushDahal 您需要按照反应规则重写整个事情。评论该部分不是解决方案,而只是确认重新安装导致失去焦点的一种方式 @Max 你有资源链接吗?我可以按照哪个正确添加列过滤器?如果你有一个这样的资源链接,你能分享一个吗?【参考方案2】:

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

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

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

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

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

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

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

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

【讨论】:

【参考方案3】:

为您的输入指定一个唯一键将导致 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>
);

看看this post

【讨论】:

在输入中添加键并不能解决问题,您能否再看一下代码,可能是因为重新渲染父元素?在每种类型上,它都会进行 api 调用,并且由于列表上的更新,整个表格组件可能会重新呈现。 您可能必须在所有父元素上指定一个键属性 我已经更新了代码并展示了我如何为每个父组件添加密钥,但仍然是同样的问题。 也必须有一个密钥。同样在 category 和 ReduxTable 中 好像我已经在 ReduxTable 上添加了 key,你能检查一下上面的代码,请说明你说的是哪个 tr?

以上是关于输入字段失去对每个字符类型的关注 - 反应的主要内容,如果未能解决你的问题,请参考以下文章

反应输入文本失去对重新渲染的关注

从字符串 => 类型的映射推断反应道具类型时修复打字稿警告

使用 redux-form 输入第一个字符后我失去了焦点

PDOStatement::fetchAll() 返回的数组中的每个字段都是字符串类型(PHP + MySQL)。如何保留原始字段类型?

为什么这个文本域失去了对morphdom的关注?

Angular2动态输入字段在输入更改时失去焦点