Según tengo entendido, useImperativeHandle ayuda al componente principal a poder llamar a la función de su componente secundario. Puedes ver un ejemplo sencillo a continuación.
const Parent = () => { const ref = useRef(null); const onClick = () => ref.current.focus(); return <> <button onClick={onClick} /> <FancyInput ref={ref} /> </> } function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } })); return <input ref={inputRef} />; } FancyInput = forwardRef(FancyInput); pero se puede lograr fácilmente usando solo useRef
const Parent = () => { const ref = useRef({}); const onClick = () => ref.current.focus(); return <> <button onClick={onClick} /> <FancyInput ref={ref} /> </> } function FancyInput(props, ref) { const inputRef = useRef(); useEffect(() => { ref.current.focus = inputRef.current.focus }, []) return <input ref={inputRef} />; } FancyInput = forwardRef(FancyInput); Entonces, ¿cuál es el verdadero objetivo de useImperativeHandle ? ¿Alguien puede darme algunos consejos?. Gracias
Probablemente algo similar a la relación entre useMemo y useCallback donde useCallback(fn, deps) es equivalente a useMemo(() => fn, deps) . A veces hay más de una manera de lograr una meta.
Diría que en el caso de useImperativeHandle , el código puede ser un poco más sucinto/ SECO cuando necesita exponer más de una propiedad.
Ejemplos:
function FancyInput(props, ref) { const inputRef = useRef(); useImperativeHandle(ref, () => ({ focus: () => inputRef.current.focus(), property, anotherProperty, ... etc ... }), []); // use appropriate dependencies ... }contra
function FancyInput(props, ref) { const inputRef = useRef(); useEffect(() => { ref.current.focus = inputRef.current.focus; ref.current.property = property; ref.current.anotherProperty = anotherProperty; ... etc ... }, []); // use appropriate dependencies ... } No es una gran diferencia, pero useImperativeHandle es menos código.
se puede lograr fácilmente usando solo
useRef
No, ¿necesita al menos otro useEffect o probablemente mejor useLayoutEffect ? E incluso entonces hace un poquito más que tu código.
useImperativeHandle(ref, () => ({ focus: () => { inputRef.current.focus(); } }));es más probable equivalente a:
// using a function. // no need to create this object over and over if there is no `ref`, // or no need to update the `ref`. const createRef = () => ({ focus: () => { inputRef.current.focus(); } }); useLayoutEffect(() => { // refs can be functions! if (typeof ref === "function") { ref(createRef()); // when the ref changes, the old one is updated to `null`. // Same on unmount. return () => { ref(null); } } // and the same thing again for ref-objects if (typeof ref === "object" && ref !== null && "current" in ref) { ref.current = createRef(); return () => { ref.current = null; } } }, [ref]);