ref doesnt set value to variable in useEffect

52 Views Asked by At

I've been doing some React crash course and got in a lot of problems. To start with,

observer.current.observe(ElemenentIGotWithRef.current) 

wasn't working in useEffect, because for some reasons the current value wasn't set at the first render.

  useEffect(()=>{
    console.log(ElemenentIGotWithRef)
  }, [])

console.log of my ElemenentIGotWithRef:

I solved it with

  useEffect(()=>{
    if (ElemenentIGotWithRef.current)
      observer.current.observe(ElemenentIGotWithRef.current);

    return (()=>{
      observer.current.disconnect();
    })
  }, [ElemenentIGotWithRef.current])

But now I am stuck with another function, which doesn't work normally because of my crutch / my unproper useEffect work.

How could I make ref set value at the first render?

1

There are 1 best solutions below

3
Ori Drori On

Usually the element is ready before useEffect is called. However, in certain situations (conditional rendering for example), the element is not ready, and the ref is not set immediately. The problem with your approach is the setting the ref.current with a new value, doesn't cause a re-render, so the useEffect might not be called when you want it. In your case, something else causes a re-render (probably the state used for the conditional render), and so you avoid this problem.

You can use useState instead of a useRef because components also accept a function as a ref. That would cause the component to re-render when the state updates with the ref:

const [ref, setRef] = useState()

useEffect(() => {
  if (ref) observer.current.observe(ref);

  return () => {
    observer.current.disconnect();
  }
}, [ref])

return (
  <ComponentWithDelayedRef ref={setRef} />
)

Another variation on the function as a ref idea, is to create a callback to observe the element, and pass it as the ref:

useEffect(() => () => {
  observer.current.disconnect();
}, [])

const observe = useCallback(el => {
  observer.current.observe(ref)
}, []);

return (
  <ComponentWithDelayedRef ref={observe} />
)