Reat 中的 useImperativeHandle 钩子函数

通过例子说明 ref 的不足

当我们需要调用子组件中的方法时,我们都是考虑使用useRef来调用子组件的方法,具体的示例代码如下:

// 父级组件
const UseImperativeHandleDemo: React.FC = () => {
  const inputRef = useRef<HTMLInputElement>(null);

  return (
    <div>
      <CustInput ref={inputRef} initVal={"123"} />
      <button onClick={() => inputRef.current?.focus()}>获取焦点</button>
    </div>
  );
};

// CustInput子组件
const CustInput = React.forwardRef<HTMLInputElement, CustInputProp>(
  (
    props: CustInputProp,
    ref: React.ForwardedRef<HTMLInputElement>
  ): JSX.Element => {
    return <input ref={ref} value={props.initVal} onChange={() => {}} />;
  }
);

这个例子中我们只是将一个引用直接传递给组件内部的单个元素,那是没有问题的,假如我们需要功能做的更加复杂一点或者需要自定义引用时,代码开发难度可能就会大大提升。

在上述例子中使用 useImperativeHandle 钩子函数扩展自定义函数

我们在上述例子的基础上使用useImperativeHandle钩子函数进行自定义函数的扩展,扩展后我们就可以在父级组件调用子组件的方法。

使用useImperativeHandle钩子函数后我们就可以在子组件中随意定义方法对外暴露方法。具体的实例如下:

const CustInput = React.forwardRef<any, CustInputProp>(
  (props: CustInputProp, ref: React.ForwardedRef<any>): JSX.Element => {
    useImperativeHandle(
      ref,
      () => {
        return { alertHi: () => alert(props.initVal) };
      },
      []
    );

    return <input value={props.initVal} onChange={() => {}} />;
  }
);

// 父组件
<button
  onClick={() => {
    inputRef.current?.alertHi(); // 调用子组件自定义的方法
  }}
>
  获取焦点
</button>;

使用 useImperativeHandle 钩子函数控制子组件中的多个元素

在上一小节我们简单实用了useImperativeHandle钩子函数进行了子组件自定义函数的扩展,在本小节中,我们可以使用useImperativeHandle钩子函数实现控制子组件中多个元素。

首先我们先看一下我们要实现的例子,具体界面如下:

在这里插入图片描述

在上述的页面中,我们的业务需求是让上述对应的按钮控制对应子组件中对应元素的焦点,我们可以在父级组件把对应的方法编写好以后传递给子组件,但是这样就会破坏单一职责原则,所以我们可以使用useImperativeHandle钩子来实现,具体的代码如下:

// 父级组件
const [open, setOpen] = useState<boolean>(false)
const modalRef = useRef<any>(null)

 <div>
  <button onClick={() => setOpen(true)}>open</button>
  <button onClick={() => modalRef.current.closeFocus()}>focus close</button>
  <button onClick={() => modalRef.current.confirmFocus()}>focus confirm</button>
  <button onClick={() => modalRef.current.denyFocus()}>focus deny</button>
  <ConfirmationModal
    ref={modalRef}
    isOpen={open}
    onClocse={() => setOpen(false)}
  />
</div>

// 子组件
const ConfirmationModal = React.forwardRef<any, ConfirmationModalProps>(
  ({ isOpen, onClocse }: ConfirmationModalProps, ref: React.ForwardedRef<any>): JSX.Element => {
    const closeRef = useRef<HTMLButtonElement>(null)
    const confirmRef = useRef<HTMLButtonElement>(null)
    const denyRef = useRef<HTMLButtonElement>(null)

    useImperativeHandle(ref, () => {
      return {
        closeFocus: () => closeRef.current?.focus(),
        confirmFocus: () => confirmRef.current?.focus(),
        denyFocus: () => denyRef.current?.focus()
      }
    }, [])

    if (!isOpen) return <></>

    return (
      <div className="modal">
        <button className="close-btn" ref={closeRef} onClick={(e) => onClocse()}>&times;</button>
        <div className="modal-header">
          <h1>title</h1>
        </div>
        <div className="modal-body">
          do yo confirm?
        </div>
        <div className="modal-footer">
          <button className="confirm-btn" ref={confirmRef} onClick={() => onClocse()}>Yes</button>
          <button className="deny-btn" ref={denyRef} onClick={() => onClocse()}>No</button>
        </div>
      </div>
    )
  }
)

总结

通过上述两个简单的例子,我们可以看到useImperativeHandle的钩子函数主要是简化我们对子组件的控制,即可以在子组件中实现自定义函数和控制子组件中的元素。这就是useImperativeHandle钩子函数的作用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React钩子函数React 16.8的新增特性,它可以让你在不编写class的情况下使用state以及其他的React特性。其最常用的钩子函数包括: 1. useState:用于在函数组件使用状态(state),并且可以进行状态数据的读写操作。 2. useEffect:用于在函数组件执行副作用操作,例如发送网络请求、订阅事件等。它接收一个回调函数和一个依赖数组作为参数,当依赖数组的值发生变化时,回调函数会被执行。 3. useContext:用于在函数组件访问Context的值。它接收一个Context对象作为参数,并返回该Context的当前值。 4. useReducer:用于在函数组件使用Reducer来管理复杂的状态逻辑。它接收一个reducer函数和初始状态作为参数,并返回当前状态和dispatch函数。 5. useCallback:用于缓存回调函数,避免不必要的重新创建。它接收一个回调函数和依赖数组作为参数,并返回一个缓存后的回调函数。 6. useMemo:用于缓存计算结果,避免不必要的重复计算。它接收一个计算函数和依赖数组作为参数,并返回缓存后的计算结果。 7. useRef:用于在函数组件获取一个可变的ref对象。它返回一个ref对象,该对象的current属性可以保存任意可变值。 8. useImperativeHandle:用于在使用ref时,自定义暴露给父组件的实例值。它接收一个ref对象和一个回调函数作为参数。 这些钩子函数可以帮助我们更方便地在函数组件管理状态、执行副作用操作和优化性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值