Why ref value is correct in useEffect but nullish in component body

Viewed 317

This is probably very trivial but Im looking for a proper answer:

Why is someRef available in useEffect, but its null in Child body?

How is it possible?

Especially when the component do not re-render. It looks like useEffect is kind of an abstract layer over component? It sounds ridiculous

const { useState, useRef } = React;

const Child = ({ someRef }) => {
  console.log('body', someRef);
  
  React.useEffect(() => {
     console.log('hiya', someRef);
  }, [someRef]);

  console.log('body', someRef);
  return null;
}

const App = () => {
  const someRef = useRef(null);

  return (
     <div>
      <div ref={someRef}>text1</div>
      <Child someRef={someRef} />
     </div>
  );
};

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>

<div id="root"></div>

1 Answers

The ref doesn't get assigned to until the App fully renders for the first time and the HTMLElements are created. When components are first mounting in an app, any refs tied to elements will initially not be defined until the initial mount cycle is completed. That's why the useEffect in Child properly displays the ref as populated with the <div>.

You don't need to wait for the someRef to change in Child (and you shouldn't, since the ref object doesn't change anyway) - all you need to do is wait for the initial mount to complete. This would work too:

const Child = ({ someRef }) => {
  React.useEffect(() => {
     console.log('hiya', someRef);
  }, []);

You can think of

<div ref={someRef}>

a bit like

<div onThisElementInsertedIntoDOM={function() { someRef.current = this; }}

Not exactly, but you get the idea. The element hasn't been inserted yet when you log them in the function body for the first time. The elements may be in the process of being created, but they haven't made it into the DOM yet.

Related