为啥在 React 中使用 useImperitaveHandle 钩子?

Posted

技术标签:

【中文标题】为啥在 React 中使用 useImperitaveHandle 钩子?【英文标题】:Why is useImperitaveHandle hook used in React?为什么在 React 中使用 useImperitaveHandle 钩子? 【发布时间】:2021-02-19 22:43:42 【问题描述】:

我找不到 useImperativeHandle Hook 的用例。尝试谷歌并了解我遇到了一个代码沙箱,其中显示了为什么使用 useImperitaveHandle Hook 的示例。这是codeandbox的链接

https://codesandbox.io/s/useimperativehandle-example-forked-illie?file=/src/App.js

我修改了代码以使其在没有下面代码框链接中的 useImperitaveHandle 的情况下工作。有人可以解释为什么要使用钩子,因为我相信没有它也可以编写代码来提供完全相同的功能。

https://codesandbox.io/s/useimperativehandle-example-forked-2cjdc?file=/src/App.js

【问题讨论】:

会不会是错字?你倒置了 i 和 a in useImperativeHandle。您可以在此处找到解释:en.reactjs.org/docs/hooks-reference.html#useimperativehandle 和另一个 SO 问题:***.com/questions/57005663/… 你能再检查一下吗,我找不到错字。我还阅读了文档以及那个 SO 问题。但两者都不令人满意。您能否举例说明为什么在代码框链接中需要使用 useImperativeHandle 你说得对,它通常可以避免。当可以通过传递道具实现相同的功能时,文档实际上建议不要使用它(以及一般的 ref 转发)。 一些 UI 组件库在输入等上使用它。我认为主要是为了让您的用户可能希望将 ref 传递给底层 DOM 元素以执行一些自定义操作包作者没有明确计划。所以他们使用 useImperativeHandle 通过 ref 来实现他们的包功能,但是 ref 转发也允许你做其他事情。 @LindaPaiste 我发现了一个用例,其中有一个无法替换 useImperativeHandler 的示例。我会回答我自己的问题,以帮助其他可能有类似问题的人 【参考方案1】:

我找到了一个可以使用它的示例。据我了解,如果您需要为库编写一些自定义功能并且需要库的一些内置功能,则主要需要它。

在我将提供的示例中,我将为库 ag-grid(表格库)编写一个自定义 CellEditor,因为我想使用 Material UI 的自动完成功能选择表格中单元格的值。下面是代码

import React,  useState, forwardRef, useImperativeHandle  from "react";

import MuiTextField from "@material-ui/core/TextField";
import MuiAutocomplete from "@material-ui/lab/Autocomplete";

const AutocompleteEditor = forwardRef(
  ( fieldToSave, fieldToShow, textFieldProps, options, ...props , ref) => 
    const [value, setValue] = useState("");

    useImperativeHandle(ref, () => 
      return 
        getValue: () => 
          return value;
        ,
        afterGuiAttached: () => 
          setValue(props.value);
        ,
      ;
    );

    const tranformValue = (value, fieldtosave) =>
      Array.isArray(value)
        ? value.map((v) => v[fieldtosave] || v)
        : value[fieldtosave];

    function onChangeHandler(e, value) 
      setValue(value ? tranformValue(value, fieldToSave) : null);
    

    return (
      <MuiAutocomplete
        style= padding: "0 10px" 
        options=options
        getOptionLabel=(item) => 
          return typeof item === "string" || typeof item === "number"
            ? props.options.find((i) => i[fieldToSave] === item)[fieldToShow]
            : item[fieldToShow];
        
        getOptionSelected=(item, current) => 
          return item[fieldToSave] === current;
        
        value=value
        onChange=onChangeHandler
        disableClearable
        renderInput=(params) => (
          <MuiTextField
            ...params
            ...textFieldProps
            style= padding: "5px 0" 
            placeholder="Select " + props.column.colId
          />
        )
      />
    );
  
);

export default AutocompleteEditor;

如果自动完成部分令人困惑,请忽略它,这对于理解 useImperativeHandler 并不重要

所以要解释代码的作用。上述组件的值由用户自动完成设置,但ag-grid表也需要该值,因为它需要更新相应单元格中的值。

它在内部使用传递给 customCellEditor 的 ref。然后 useImperativeHook 告诉 ag-grid 在调用 getValue 时使用组件状态中的值(当单元格需要显示值时调用它)

【讨论】:

以上是关于为啥在 React 中使用 useImperitaveHandle 钩子?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Vue.js 或 React 中使用组件? [关闭]

React,为啥在 ES6 类构造函数中使用 super(props)? [复制]

为啥 getElementsByClassName 在 React 功能组件中返回未定义?

为啥我在使用 create-react-app 的生产构建中丢失了 Bootstrap 样式?

为啥我在使用 Prisma(React 应用程序)在 Mongodb 中显示和删除时遇到问题?

为啥我不能使用 react.createContext()