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> });
I try to use a child method in a parent component using ref
and React.useImperativeHandle()
.
It works well.
but I am not satisfied because of const cntEl:any
.
I believe there are many ways to avoid using any
type I don't know.
I just need a type that could be replaced type any
.
Edited
I can see (property) React.MutableRefObject<null>.current: null
when I hover at cntEl.current
React useImperativeHandle Hook In React, data is passed from parent to child components via props, known as unidirectional data flow. The parent component cannot directly call a function defined in the child component or reach down to grab a value for itself.
Use useMemoThe useMemo Hook accepts a second parameter to declare dependencies. The expensive function will only run when its dependencies have changed. In the following example, the expensive function will only run when count is changed and not when todo's are added.
While there's currently no React Hook that does this out of the box, you can manually retrieve either the previous state or props from within a functional component by leveraging the useRef , useState , usePrevious , and useEffect Hooks in React.
I recommend you use type definitions more explicitly
For example, with React DT, you can define ref exotic component with ForwardRefRenderFunction
instead of 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);
and then use React utility ElementRef
, TypeScript can infer exact ref type of your component
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} /> ); };
The accepted answer is overcomplicated, you just need to declare a CountdownHandle
type.
For me it'll go like this:
// 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} />; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With