0

i'm creating a react app with useMemo.
The memo uses empty array as the dependency list, so it should be executed once, right?

Inside the memo, there are console.log() & counter++ to visualize how many times the memo get executed.

Magically, I got one log but the counter seems executed twice.

See this sandbox or see the code below:

import {
    useMemo,
}                           from 'react'


let counter = 0;
export default function App() {
    const foo = useMemo(() => {
        console.log('increase counter');

        counter++;
    }, []);


    return (
        <p>
            {counter}
        </p>
    );
}

enter image description here

Heyyy Marco
  • 633
  • 1
  • 12
  • 22
  • Check this link: [usememo](https://github.com/facebook/react/issues/17186#issuecomment-546553979) – Medi Jul 29 '21 at 13:03

1 Answers1

0

It looks like you're incorrectly using useMemo

A useMemo() computes something only when something in its dependancy array changes. It looks like you haven't given the dependancy array any variables.

Please review this example of useMemo:

export default function App() {
const [loading, setLoading] = useState(true);
const component = useMemo(() => {
    if(loading){
  return <div>Loading...</div>
} else {
  return <div>Finished Loading</div>
}, [loading]);


return (
    <div>
        {component}
    </div>
);
}

As you can see from this example when the state changes the useMemo is computed.

In your above example, I imagine the useMemo is being computed twice because its happening each time the page renders.

For your counter example I would recommend just using useState.

 export default function App() {
const [counter, setCounter] = useState(0);

return (
    <div>
        <p>{counter}</p>
        <button onClick={() => setCounter(prevState => prevState++)}>Increase Counter</button>
    </div>
);
}

EDIT: This question was actually resolved in the comments. Disabling StrictMode prevents the double re-render.

Will T
  • 647
  • 5
  • 16
  • Yes i know i'm abusing the `useMemo`, it should use `use(Layout)Effect`. It's the investigation why my code got executed twice, so i created the code above to inspect whats happened. Then i realized the memo got executed twice. – Heyyy Marco Jul 29 '21 at 12:55
  • Ah, I updated my answer, apologies for not being clearer. Your code is being computed twice as something is causing your page to render twice. Its also not recommended to use useMemo without a dependancy array as it cause unstable side effects – Will T Jul 29 '21 at 12:59
  • i've tested by modifying `const somethingNeverMutated = {}` and `[somethingNeverMutated]`. Since the dependency is never changed, the memo should executed once but got twice. – Heyyy Marco Jul 29 '21 at 13:02
  • I added `console.log("render");` before the `return

    ...

    ` and i got one render log. So i belived the page rendered once.

    – Heyyy Marco Jul 29 '21 at 13:08
  • i've commented all the logs and got the counter = 2 – Heyyy Marco Jul 29 '21 at 13:11
  • 1
    I've found this duplicate. https://stackoverflow.com/questions/61549481/react-render-twice-with-hooks – Will T Jul 29 '21 at 13:12
  • 2
    I think turning off StrictMode may resolve your issue. – Will T Jul 29 '21 at 13:14
  • i suspected the react **secretly** executes the second memo while disabling the log function. – Heyyy Marco Jul 29 '21 at 13:15
  • oh yess, finally the `` is the root of my problem. I don't know why react doing this. – Heyyy Marco Jul 29 '21 at 13:18