Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

100
Views
How React.memo works with useCallback

As far as I understand, React.memo is an API that memoize a component: if its props don't change, react use the latest render of that component without comparing it with its previous version. Skipping this comparing speed-up the app. Cool.

Now, here's what I don't get: if props don't change, also a not memoized component don't get re-rendered, as I can see from that simple code: there's no difference about number of renders between a normal component+usecallback and a memoized one+useCallback. Basically, useCallbacks is all I need, as a normal component doesn't get re-rendered with same props. Then, what I'm I missing? When memo comes in help to optimize?

import { useCallback, useEffect, useState, memo, useRef } from "react";
import "./styles.css";

function Child({ fn, txt }) {
  const [state, setState] = useState(0);
  console.log(txt + " rendered!");

  useEffect(() => {
    setState((state) => state + 1);
  }, [fn]);

  return (
    <div style={{ border: "solid" }}>
      I'm a Child
      {!fn && <div>And I got no prop</div>}
      {fn && <div>And I got a fn as a prop</div>}
      <div>and I've got rendered {state} times</div>
    </div>
  );
}

const MemoChild = memo(({ fn, txt }) => {
  const [state, setState] = useState(0);
  const counter = useRef(0);
  console.log(txt + " rendered!", counter.current);

  useEffect(() => {
    setState((state) => state + 1);
    counter.current++;
  }, [fn]);

  return (
    <div style={{ border: "solid" }}>
      I'm a Child
      {!fn && <div>And I got no prop</div>}
      {fn && <div>And I got a fn as a prop</div>}
      <div>and I've got rendered {state} times</div>
    </div>
  );
});

export default function App() {
  const [, setState] = useState(true);

  const handlerOfWhoKnows = () => {};

  return (
    <div className="App">
      I'm the parent
      <br />
      <button onClick={() => setState((state) => !state)}>
        Change parent state
      </button>
      <h3>Ref</h3>
      ref: <Child txt="ref" fn={handlerOfWhoKnows} />
      <h3>useCallback test</h3>
      useCB: <Child txt="useCb" fn={useCallback(handlerOfWhoKnows, [])} />
      memo: <Child txt="memo" fn={handlerOfWhoKnows} />
      memo + useCB:{" "}
      <MemoChild txt="memo+useCb" fn={useCallback(handlerOfWhoKnows, [])} />
    </div>
  );
}
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

Your example is misleading you a bit because you never change the state of App.

Now, here's what I don't get: if props don't change, also a not memoized component don't get re-rendered...

That's incorrect. If the parent re-renders, an unmemoized child will re-render, even if its props don't change.

When memo comes in help to optimize?

When you don't want that to happen. :-)

Here's an example, notice that Unmemoized re-renders as the counter goes up , but Memoized does not; neither of them uses the counter, so neither of them needs to re-render, but the unmemoized one does anyway because that's the default behavior:

const { useState, useEffect } = React;

const Unmemoized = ({ value }) => {
    console.log(`Unmemoized rendering with "${value}"`);
    return <div>Unmemoized: {value}</div>;
};

const Memoized = React.memo(({ value }) => {
    console.log(`Memoized rendering with "${value}"`);
    return <div>Memoized: {value}</div>;
});

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

    useEffect(() => {
        const timer = setInterval(() => {
            setCounter(c => {
                ++c;
                if (c === 5) {
                    clearInterval(timer);
                }
                return c;
            });
        }, 800);
        return () => {
            clearInterval(timer);
        };
    }, []);

    return (
        <div>
            <div>Counter: {counter}</div>
            <Memoized value="a" />
            <Unmemoized value="b" />
        </div>
    );
};

const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(<Example />);
<div id="root"></div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!