Why does my React component rerender automatically?

I have a simple React component and when I inspect the console what I logged appears 3 times.

The Load APP log comes from my main App.js component and Load New from the component rendered by the Navigation in App.js : FasList.js.

Why do I see 3 logs when I only log one time in my component ?

Log output

I did a second test with a log in a useEffect :

Second Log output with useEffect

Here is the code in App.hjs :

    console.log('APP');

    useEffect(() => {
        fetchAuthStatus();
        console.log("I'm in useEffect");
    }, []);

Does the log output repeating itself have something to do with the way React works ?

According to the second test, the component only renders 1 times but still 3 APPlog

Here is a working example of the problem with my 2 components : https://stackblitz.com/edit/logs-output-demo

Answers:

Answer

The body of your component function runs every time the component gets rendered. Your component get rendered any time React thinks that's necessary, but typically once when initially added to the page and then again whenever its state changes. (Several state changes done at the same time typically only result in a single render, but if there's any gap between them, rendering will happen after each.)

Code in a useEffect hook callback runs after rendering the first time, and then again any time one of the dependencies you list changes. Since your code isn't listing any dependencies, the hook callback only runs once.

Here's a simple example:

const {useState, useEffect} = React;

const Example = () => {
    const [counter, setCounter] = useState(0);
    const [flag, setFlag] = useState(false);

    // Runs after initial render, then again every time `flag` changes
    useEffect(() => {
        console.log(`useEffect #1 ran, flag = ${flag}`);
    }, [flag]);

    // Runs after initial render, then every time `flag` or
    // `counter` changes
    useEffect(() => {
        console.log(`useEffect #2 ran, flag = ${flag}, counter = ${counter}`);
    }, [flag, counter]);
    
    // Runs after initial render only
    useEffect(() => {
        console.log(`useEffect #3 ran`);
    }, []);
    
    return (
        <div>
            <input type="button" value="Increment" onClick={() => setCounter(c => c + 1)} />
            <input type="button" value="Flip Flag" onClick={() => setFlag(f => !f)} />
        </div>
    );
};

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

You may find this article by Dan Abramov useful. It goes into depth about how React renders, in the context of explaining useEffect (but it's a useful read even separate from understanding useEffect).

Answer

You are changing state 1 more time with fetchAuthStatus() method, so a re-render happens. This does not mean that the DOM is changed twice.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.