在 Reactjs 中使用 useRef 从父函数调用子函数

Nav*_*nam 5 typescript reactjs use-ref

该代码是使用 React 功能组件编写的。

单击父级中的按钮后,应触发函数 showAlert。这就是要求。

目前在父组件childRef.current中无法调用showAlert()函数。我收到打字稿错误

Property 'showAlert' does not exist on type 'ForwardRefExoticComponent<RefAttributes<unknown>>'

父功能组件代码

import React, { forwardRef, useRef, useImperativeHandle } from 'react';
import Child from './Child';
export default function App() {
  const childRef = useRef<typeof Child>(Child);
  return (
    <div className="container">

      <Child ref={childRef} />
      <button
        onClick={() => { childRef.current.showAlert() }}
      >
        Call Function
            </button>
      
    </div>
  )
}
Run Code Online (Sandbox Code Playgroud)

子功能组件

import React, { forwardRef, useRef, useImperativeHandle } from 'react';

const Child = forwardRef((props, ref) => {
    useImperativeHandle(
        ref,
        () => ({
             showAlert() {
                alert("Child Function Called")
                console.log('hello world')
            }
        }),
    )
    return (
        <div>Child Component</div>
    )
})

export default Child
Run Code Online (Sandbox Code Playgroud)

Lin*_*ste 20

你已经得到了这几乎是正确的,但typeof Child没有给你一个准确的类型,因为Child组件本身的类型不够严格。它被推断为forwardRef<unknown, {}>. 我们需要指定转发引用的类型才能使其正常工作。

我们可以为我们想要的 ref 定义一个接口:

interface CanShowAlert {
  showAlert(): void;
}
Run Code Online (Sandbox Code Playgroud)

我们在函数上设置了两个泛型forwardReffor ChildCanShowAlert是 ref 类型,{}是 props 类型:

const Child = forwardRef<CanShowAlert, {}>((props, ref) => {
Run Code Online (Sandbox Code Playgroud)

我们在 上使用相同的泛型useRef

const childRef = useRef<CanShowAlert>(null);
Run Code Online (Sandbox Code Playgroud)

您的初始值会出现错误useRef<CanShowAlert>(Child),因为 ref 是针对组件的实例,但您传入的是组件函数本身。相反,我们使用null作为初始值。

ref 的属性current要么是组件实例,要么是,因此我们需要在调用函数之前null确保它不是。为此,我们可以使用可选的链接运算符。nullshowAlert?.

childRef.current?.showAlert()
Run Code Online (Sandbox Code Playgroud)

完整代码:

import React, {forwardRef, useRef, useImperativeHandle} from "react";

interface CanShowAlert {
  showAlert(): void;
}

export default function App() {
  const childRef = useRef<CanShowAlert>(null);
  return (
    <div className="container">

      <Child ref={childRef} />
      <button
        onClick={() => { childRef.current?.showAlert() }}
      >
        Call Function
            </button>
      
    </div>
  )
}


const Child = forwardRef<CanShowAlert, {}>((props, ref) => {
    useImperativeHandle(
        ref,
        () => ({
             showAlert() {
                alert("Child Function Called")
                console.log('hello world')
            }
        }),
    )
    return (
        <div>Child Component</div>
    )
})
Run Code Online (Sandbox Code Playgroud)