useEffect runs prior to rendering?

Viewed 3105
export default function Example() {

   useEffect(()=>{
       console.log('DOM has not rendered anything yet')
   });

    return (
        <div>
            Hello
        </div>
    );
}

What am I getting with the above code is the console message first and then Hello appears on my page. However, by debugging the code I can see return precedes useEffect. Why then Hello is not visible when useEffect runs for the first time?

enter image description here

Moreover, if using the code from https://reactjs.org/docs/hooks-effect.html#example-using-hooks:

function Example() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  });

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

seeing that when callback of useEffect is being executed for the first time, only the button is visible not You clicked 0 times.

3 Answers

See the hooks-effect docs

What does useEffect do? By using this Hook, you tell React that your component needs to do something after render. React will remember the function you passed (we’ll refer to it as our “effect”), and call it later after performing the DOM updates. In this effect, we set the document title, but we could also perform data fetching or call some other imperative API.

Here is your code, you can open the devtools and see that hello is rendered when the debugger statement pauses your code. This is how React behaves as documented and as 2 people already pointed out.

const { useState, useEffect } = React;
function App() {
  useEffect(() => {
    debugger;
    console.log('last');
  });
  console.log('first');
  //this is returned and react will render this to dom before
  //  your effect is called as documented and as 2 people already pointed out
  return <div>Hello</div>;
}

ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>

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

Try running this code and see the order of the log messages.


function App() {

  useEffect(() => {
    console.log('DOM has not rendered anything yet')
  });

  function hello() {
    console.log("render")
  }

  return (
    <div onClick={hello()} >
      Hello
    </div>
  );

}

useEffect is like componentDidMount in that it runs after the first render and after each update to the dom.

The code above demonstrates that render is called first followed by useEffect.

Related