处理 useRef + useImperativeHandle :Property ‘xxx‘ does not exist on type ‘never‘. 的类型错误

useImperative 这个 hook 可以自定义一个对象,暴露给父组件。

这个 hook 一般结合 forwardRef 一起使用,实现父组件去调用子组件中的实例属性 or 方法,进而操作子组件的 DOM

那么使用 useImperativeforwardRef 时如何定义类型呢?

我们通过一个简单栗子 🌰 来学习一下 :

先定义一个组件:

const Countdown = React.forwardRef((props,ref) => {
  React.useImperativeHandle(ref, ()=>({
    start() {
      alert('Start');
    }
  });
  return <div>Countdown</div>
});

在父组件中引用该组件:

function App(){
  const cntEl:any = React.useRef(null);
  
  React.useEffect(()=>{
    if(cntEl.current){ cuntEl.current.start() }
  }, []);
  
  return <Countdown ref={cntEl} />
}

很多人会这样写,把 TypeScript 变成 AnyScript,对于 cuntEl.current.start() 还报的 Property 'start' does not exist on type 'never'. 错误 ,直接 // @ts-ignore 把错误干掉。

既然解决不了问题,那就解决提出问题的人。

Figure 1

我们需要做几件限定类型安全的事情:

  1. 限定 Props 类型。
  2. 限定在 useImperativeHandle 定义的对象类型。
  3. 限定 useRef 中的类型。
type CountdownProps = {}
    
type CountdownHandle = {
  start: () => void,
}

// 利用 React 提供的 ForwardRefRenderFunction 去限定 CountdownHandle 和 CountdownProps
const Countdown: React.ForwardRefRenderFunction<CountdownHandle, CountdownProps> = (
  props,
  forwardedRef,
) => {
  React.useImperativeHandle(forwardedRef, ()=>({
    start() {
      alert('Start');
    }
  });

  return <div>Countdown</div>;
}

export default React.forwardRef(Countdown);
import Countdown, { CountdownHandle } from "./Countdown.tsx";

function App() {
  // 限定 useRef 的类型为 CountdownHandle,这样调用 start 不会报错
  const countdownEl = React.useRef<CountdownHandle>(null);

  React.useEffect(() => {
    if (countdownEl.current) {
      countdownEl.current.start();
    }
  }, []);

  return <Countdown ref={countdownEl} />;
}

记住,一定要利用好 TypeScript,保障好类型安全,避免 AnyScript。

我是 Pandy,一个喜欢英语的程序猿 👨‍💻

关注公众号 Yopth,回复「加群」,加入「英文技术翻译互助群」,我们加入一起充电英语 🔌

Reference

[1] https://stackoverflow.com/questions/62210286/declare-type-with-react-useimperativehandle
[2] https://reactjs.org/docs/hooks-reference.html#useimperativehandle

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值