En mi aplicación, hay cierta lógica de UX que debe compartirse. Se desencadenan por eventos, así que escribí 2 ganchos personalizados. Llamemos a uno useRefWithCalc . El otro hook es un useEventListener más estándar, similar a este .
useRefWithCalc llama al useRef nativo, tiene algunos controladores internos para UX, luego llama a useEventListener para adjuntar esos controladores. useRefWithCalc devuelve la ref creada dentro, por lo que otro componente puede usar este enlace y obtener la referencia devuelta para adjuntarla a los elementos.
Esto me ha funcionado cuando la referencia no está adjunta a elementos renderizados condicionalmente.
El componente se parece a esto. Tome nota de los 2 registros de prueba.
const useEventListener = (event, listener, ref) => {\ ... useEffect(() => { ... console.log("1. ref is: ", ref.current); // test logging 1. ref.current.addEventListener(event, listener); return () => { ref.current.removeEventListener(event, listener); } }, [event, listener, ref]); } const useRefWithCalc = (value) => { const ref = useRef(null); ... const calc = () => { // some calculations } ... useEventListener(event, calc, ref) return [ref, result] } // works perfectly const WorkingElement = (props) => { const [ref, result] = useRefWithCalc(props.value); ... return <B ref={ref} /> } // doesn't work consistently const ConditionalElement = (props) => { const [state, setState] = useState(false); const [ref, result] = useRefWithCalc(props.value) useEffect(()=>{ if (ref && ref.current) { ref.current.focus(); console.log("2. ref is: ", ref.current); // test logging 2 } }, [ref]) ... return state ? <A> : <B ref={ref} /> } El <WorkingElement /> funciona como se esperaba. La referencia se adjunta y maneja los eventos sin problemas.
Sin embargo, en <ConditionalElement /> , cuando B está montado, a veces el registro de prueba 1 no se activa. El registro de prueba 2 siempre se activa y el árbitro recibe el enfoque correctamente. Pero esta actualización no se pasa a useEventListener
Una vez que <B /> obtiene 1 actualización posterior (por ejemplo, cuando el usuario ingresa algo), ambos registros se activarán correctamente y el listado de eventos se adjuntará correctamente y funcionará como <WorkingElement />
Lo siento por no publicar el código exacto. Siento que mi enfoque es intrincado y podría estar equivocado.
En React, cuando cambia una referencia, no activa una actualización de componente y no se activan useEffect s.
Sugiero poner su referencia dentro de un estado para que los efectos se activen cuando cambie la referencia:
const [ref, setRef] = useState(undefined) return ( <B ref={setRef}/> )