Búsqueda de sitios web

reactjs - declarar tipo con React.useImperativeHandle()


function App(){
  const cntEl:any = React.useRef(null);  // I don't know what type should be here.
  React.useEffect(()=>{
    if(cntEl.current){ cuntEl.current.start() }
  }, []);
  return <Countdown ref={cntEl} />
}
const Countdown = React.forwardRef((props,ref) => {
  React.useImperativeHandle(ref, ()=>({
    start() {
      alert('Start');
    }
  });
  return <div>Countdown</div>
});

Intento usar un método de un componente hijo en un componente padre usando ref y React.useImperativeHandle().

Funciona bien.

pero no estoy satisfecho debido a const cntEl:any.

Creo que hay muchas maneras de evitar usar el tipo any que no conozco.

Solo necesito un tipo que pueda ser reemplazado por el tipo any.

Editado

Puedo ver (property) React.MutableRefObject<null>.current: null cuando paso el cursor sobre cntEl.current

Respuesta #1

La respuesta aceptada está demasiado complicada, solo necesitas declarar un tipo CountdownHandle.

Para mí será así:

// Countdown.tsx

export type CountdownHandle = {
  start: () => void;
};

type Props = {};

const Countdown = React.forwardRef<CountdownHandle, Props>((props, ref) => {
  React.useImperativeHandle(ref, () => ({
    // start() has type inferrence here
    start() {
      alert('Start');
    },
  }));

  return <div>Countdown</div>;
});
// The component uses the Countdown component

import Countdown, { CountdownHandle } from "./Countdown.tsx";

function App() {
  const countdownEl = React.useRef<CountdownHandle>(null);

  React.useEffect(() => {
    if (countdownEl.current) {
      // start() has type inferrence here as well
      countdownEl.current.start();
    }
  }, []);

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

Respuesta #2

Te recomiendo que uses definiciones de tipo de manera más explícita

Por ejemplo, con React DT, puedes definir un componente exótico ref con ForwardRefRenderFunction en lugar de FC.

type CountdownProps = {}
    
type CountdownHandle = {
  start: () => void,
}
    
const Countdown: React.ForwardRefRenderFunction<CountdownHandle, CountdownProps> = (
  props,
  forwardedRef,
) => {
  React.useImperativeHandle(forwardedRef, ()=>({
    start() {
      alert('Start');
    }
  });

  return <div>Countdown</div>;
}

export default React.forwardRef(Countdown);

y luego usa la utilidad de React ElementRef, TypeScript puede inferir el tipo exacto de ref de tu componente

const App: React.FC = () => {
  // this will be inferred as `CountdownHandle`
  type CountdownHandle = React.ElementRef<typeof Countdown>;

  const ref = React.useRef<CountdownHandle>(null); // assign null makes it compatible with elements.

  return (
    <Countdown ref={ref} />
  );
};

Artículos relacionados