Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DevTools Bug]: The memo component is not displayed correctly #32485

Open
spencer17x opened this issue Feb 27, 2025 · 6 comments
Open

[DevTools Bug]: The memo component is not displayed correctly #32485

spencer17x opened this issue Feb 27, 2025 · 6 comments
Labels
Component: Developer Tools Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug

Comments

@spencer17x
Copy link

Website or app

None

Repro steps

"use client";
import { memo, useState } from "react";

const A = () => {
  console.log("render A");

  return <div>A</div>;
};

const B = memo(function B() {
  console.log("render B");

  return <div>B</div>;
});

function App() {
  const [count, setCount] = useState(0);
  return (
    <>
      <div onClick={() => setCount(count + 1)}>App: {count}</div>
      <A />
      <B />
    </>
  );
}

export default App;
Image

When displayName is used, the memo component will be displayed without 🧠.

How often does this bug happen?

Every time

DevTools package (automated)

No response

DevTools version (automated)

No response

Error message (automated)

No response

Error call stack (automated)


Error component stack (automated)


GitHub query string (automated)


@spencer17x spencer17x added Component: Developer Tools Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug labels Feb 27, 2025
@Hardik8491
Copy link

Hardik8491 commented Feb 28, 2025

Fix Issue #32485

To properly prevent re-renders of B, ensure that:

B is wrapped in memo (which you already did).
A is also wrapped in memo to prevent unnecessary re-renders.

"use client";
import { memo, useState } from "react";

const A = memo(function A() { // Memoized A
console.log("render A");
return

A
;
});

const B = memo(function B() {
console.log("render B");
return

B
;
});

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

return (
<>
<div onClick={() => setCount(count + 1)}>App: {count}


</>
);
}

export default App;

@Mayank6787
Copy link

"use client";
import { memo, useState } from "react";

// Memoized Component A
const A = memo(function A() {
console.log("render A");
return

A
;
});

// Memoized Component B
const B = memo(function B() {
console.log("render B");
return

B
;
});

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

return (
<>
<div onClick={() => setCount(count + 1)}>App: {count}


</>
);
}

export default App;

Optimizing React Components with memo()

1. JSX Return Issue

In the previous code, the return statements for components A and B were incorrect because JSX elements must be placed on the same line as return or wrapped in parentheses. This issue was fixed by ensuring proper JSX syntax with:

return <div>A</div>;
return <div>B</div>;

2. Memoization and Re-renders

The memo() function in React prevents re-renders of a component when its props do not change. Since A and B do not have any props, they should not re-render when the App component updates. However, if they do, it is likely due to React's Strict Mode in development.

3. Strict Mode and Double Rendering

React Strict Mode, which is enabled by default in some setups, intentionally renders components twice in development to help detect side effects. This can create confusion when testing performance optimizations like memo(). To verify whether memo() is working correctly, testing in production mode using the following command can help:

npm run build && npm start

Alternatively, disabling Strict Mode in main.js can also help:

import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";

ReactDOM.createRoot(document.getElementById("root")).render(
  <App /> // Remove <React.StrictMode> to prevent double renders
);

4. Ensuring Optimization Works

To confirm that memo() is effectively preventing unnecessary re-renders, passing props to B, such as:

<B value="fixed" />

can help test whether it re-renders when count in App updates. If B does not re-render, it confirms that memo() is working correctly.

Final Thoughts

By ensuring correct JSX syntax, understanding how memo() prevents re-renders, and recognizing the impact of React's Strict Mode, we can optimize component rendering efficiently. The updated code properly applies memo() to A and B, preventing unnecessary re-renders as long as they do not receive new props. If re-renders still occur unexpectedly, disabling Strict Mode in development or testing in production can confirm whether memo() is functioning as expected. This approach helps in optimizing React applications by reducing redundant renders and improving performance.

@spencer17x
Copy link
Author

I tested it and it has nothing to do with strict mode

@L00kAhead
Copy link

@spencer17x
Hi, you are using the Named Function Expression inside the memo().React DevTools can infer the name of the component (in this case, B) without you needing to manually set displayName. This happens because React memoizes the function and, since the function is named, it can automatically use that name in the DevTools.

const B = memo(function B() {
  console.log("render B");

  return <div>B</div>;
});

However, if you later try to set B.displayName = 'B' after the declaration, it won't show up correctly in React DevTools. This is because memo essentially wraps the component, and after memoizing, React DevTools doesn't directly reference the original function name, so it doesn’t use the manually set displayName. The name assigned through the memoization process is the one React DevTools will display.

Work around:

  • Define your component as a named function and assign the displayName property before wrapping it with memo(). This approach helps DevTools recognize and display the component's name accurately.
const BComponent = function B() {
  console.log("render B");
  return <div>B</div>;
};

BComponent.displayName = "B";

const B = memo(BComponent);
  • Or you can provide a second argument as an options object where you can set the displayName. This ensures that DevTools display the component with the specified name.
const B = memo(
  function B() {
    console.log("render B");
    return <div>B</div>;
  },
  {
    displayName: "B"
  }
);
issue-32485.mp4

@spencer17x
Copy link
Author

spencer17x commented Mar 3, 2025

@spencer17x Hi, you are using the Named Function Expression inside the memo().React DevTools can infer the name of the component (in this case, B) without you needing to manually set displayName. This happens because React memoizes the function and, since the function is named, it can automatically use that name in the DevTools.

const B = memo(function B() {
  console.log("render B");

  return <div>B</div>;
});

However, if you later try to set B.displayName = 'B' after the declaration, it won't show up correctly in React DevTools. This is because memo essentially wraps the component, and after memoizing, React DevTools doesn't directly reference the original function name, so it doesn’t use the manually set displayName. The name assigned through the memoization process is the one React DevTools will display.

Work around:

  • Define your component as a named function and assign the displayName property before wrapping it with memo(). This approach helps DevTools recognize and display the component's name accurately.
const BComponent = function B() {
  console.log("render B");
  return <div>B</div>;
};

BComponent.displayName = "B";

const B = memo(BComponent);
  • Or you can provide a second argument as an options object where you can set the displayName. This ensures that DevTools display the component with the specified name.
const B = memo(
  function B() {
    console.log("render B");
    return <div>B</div>;
  },
  {
    displayName: "B"
  }
);

issue-32485.mp4

I think maybe devtools should fix it?

@L00kAhead
Copy link

I reckon an improved documentation with best practices would be a reasonable solution as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: Developer Tools Status: Unconfirmed A potential issue that we haven't yet confirmed as a bug Type: Bug
Projects
None yet
Development

No branches or pull requests

4 participants