reactjs - הכרז על סוג עם 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>
});

אני מנסה להשתמש בשיטה של ילד בתוך קומפוננטת אב באמצעות ref ו-React.useImperativeHandle().

זה עובד טוב.

אבל אני לא מרוצה בגלל const cntEl:any.

אני מאמין שיש דרכים רבות להימנע משימוש בסוג any שאני לא יודע.

אני פשוט צריך סוג שניתן להחליף את הסוג any.

נערך

אני יכול לראות (property) React.MutableRefObject<null>.current: null כשאני מרחף מעל cntEl.current

תשובה #1

התשובה המקובלת יותר מדי מסובכת, אתה רק צריך להצהיר על סוג CountdownHandle.

בשבילי זה יהיה ככה:

// 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} />;
}

תשובה #2

אני ממליץ לך להשתמש בהגדרות סוגים בצורה ברורה יותר

לדוגמה, עם React DT, אתה יכול להגדיר קומפוננטה ייחודית עם ref באמצעות ForwardRefRenderFunction במקום 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);

ואז להשתמש בתגי React ElementRef, TypeScript יכול להסיק את סוג ה-ref המדויק של הקומפוננטה שלך

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} />
  );
};