Вызов дочерней функции из родительского в Reactjs с использованием useRef

Код написан с использованием функциональных компонентов 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

person Naveen Gorojanam    schedule 25.02.2021    source источник
comment
Вы почти закончили, но есть несколько типов машинописных текстов, которые вам нужно заполнить в Child. Я могу написать ответ.   -  person Linda Paiste    schedule 25.02.2021
comment
@LindaPaiste, не могли бы вы написать ответ. Было бы очень полезно   -  person Naveen Gorojanam    schedule 25.02.2021


Ответы (2)


Вы почти правильно поняли, но typeof Child не дает вам точного типа, потому что сам компонент Child не типизирован достаточно строго. Предполагается, что это forwardRef<unknown, {}>. Нам нужно указать тип пересылаемой ссылки, чтобы это работало.

Мы можем определить интерфейс для ссылки, которую мы хотим:

interface CanShowAlert {
  showAlert(): void;
}

Мы устанавливаем два дженерика на функцию forwardRef для Child. CanShowAlert — это тип ссылки, а {} — тип реквизита:

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

Мы используем тот же универсальный код на useRef:

const childRef = useRef<CanShowAlert>(null);

Вы получаете сообщение об ошибке с начальным значением useRef<CanShowAlert>(Child), потому что ссылка предназначена для экземпляра компонента, но вы передаете саму функцию компонента. Вместо этого мы используем null в качестве начального значения.

Свойство current ссылки будет либо экземпляром компонента, либо null, поэтому нам нужно убедиться, что это не null, прежде чем мы вызовем функцию showAlert. Для этого мы можем использовать необязательный оператор цепочки ?..

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>
    )
})
person Linda Paiste    schedule 25.02.2021

Попробуйте так

useImperativeHandle(
        ref,
        () => ({
             showAlert: () => { // like this here
                alert("Child Function Called")
                console.log('hello world')
            }
        }),
)
person Nooruddin Lakhani    schedule 25.02.2021
comment
Он говорит Property 'showAlert' does not exist on type 'ForwardRefExoticComponent<RefAttributes<unknown>>' Является ли объявление useRef здесь неправильным? - person Naveen Gorojanam; 25.02.2021