使用 useRef 从 Reactjs 中的父级调用子函数

Posted

技术标签:

【中文标题】使用 useRef 从 Reactjs 中的父级调用子函数【英文标题】:Call Child Function from Parent in Reactjs using useRef 【发布时间】:2021-02-25 06:14:39 【问题描述】:

代码是使用 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>
  )

子功能组件

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

【问题讨论】:

您快到了,但是您需要在 Child 上填写一些 typescript 类型。我可以写一个答案。 @LindaPaiste 请你写下答案。真的很有帮助 【参考方案1】:

这几乎是正确的,但typeof Child 没有给你一个准确的类型,因为Child 组件本身的类型不够严格。它被推断为forwardRef&lt;unknown, &gt;。我们需要明确转发的 ref 的类型才能使其正常工作。

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

interface CanShowAlert 
  showAlert(): void;

我们在forwardRef 函数上为Child 设置了两个泛型。 CanShowAlert 是 ref 类型, 是 props 类型:

const Child = forwardRef<CanShowAlert, >((props, ref) => 

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

const childRef = useRef<CanShowAlert>(null);

您的初始值 useRef&lt;CanShowAlert&gt;(Child) 出现错误,因为 ref 是针对组件的 instance 的,但您传入的是组件函数本身。相反,我们使用null 作为初始值。

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

childRef.current?.showAlert()

完整代码:

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>
    )
)

【讨论】:

【参考方案2】:

试试这个方法

useImperativeHandle(
        ref,
        () => (
             showAlert: () =>  // like this here
                alert("Child Function Called")
                console.log('hello world')
            
        ),
)

【讨论】:

上面写着 Property 'showAlert' does not exist on type 'ForwardRefExoticComponent&lt;RefAttributes&lt;unknown&gt;&gt;' 这里的 useRef 声明错了吗?

以上是关于使用 useRef 从 Reactjs 中的父级调用子函数的主要内容,如果未能解决你的问题,请参考以下文章

reactjs中未从父级调用子组件函数

从reactjs中的父组件调用子组件方法

从木偶中的父级扩展 Coffeescript 子类函数

从reactjs中的父组件调用并将参数传递给子组件的函数

如何从 TypeScript 文件中的父级获取子组件变量和函数

有没有办法从VueJS中的父级触发组件方法?