How to fix Multiple components with the same displayName in React
This debugging issue occurs when multiple React components share identical displayName values, making it difficult to distinguish between them in React DevTools. While not a runtime error, it creates confusion during development and debugging.
Quick fix
Fixes Multiple components with the same displayName
# Install ESLint plugin if not already present
npm install --save-dev eslint-plugin-react- Identify components with duplicate displayNames
- Set explicit displayName for function components
- Fix displayName for React.memo components
- Configure displayName for React.forwardRef
# Install ESLint plugin if not already presentnpm install --save-dev eslint-plugin-reactMultiple components with the same displayName
What this error means
The displayName property in React is a string used primarily for debugging purposes. React DevTools and other debugging tools use displayName to identify components in the component tree. When multiple components share the same displayName, it becomes challenging to differentiate between them during debugging sessions. This issue commonly arises when using higher-order components (HOCs), React.memo, React.forwardRef, or when creating components dynamically. Unlike a runtime error, duplicate displayNames don't break your application but significantly hamper the debugging experience by making it unclear which component instance you're inspecting in DevTools. The React DevTools component tree relies on displayName to present a readable component hierarchy. When displayNames collide, you may see multiple instances labeled identically, making it impossible to determine which component corresponds to which part of your UI without additional investigation.
Typical symptoms
- Multiple components showing identical names in React DevTools component tree
- Difficulty identifying specific component instances during debugging
- Confusion when inspecting component props or state in DevTools
- ESLint warnings about missing or duplicate displayName properties
- Anonymous components appearing as "<Unknown>" or "<Component>" in error stack traces
- Styled-components or HOCs showing generic wrapper names instead of meaningful identifiers
Common causes
- Using React.memo without setting a unique displayName on the wrapped component
- Higher-order components (HOCs) that wrap multiple components without generating unique displayNames
- React.forwardRef components lacking explicit displayName assignments
- Creating components dynamically in loops or maps without unique naming
- Exporting anonymous function components without assigned names or displayName properties
- Using styled-components or other CSS-in-JS libraries without configuring displayName generation
- Context.Provider and Context.Consumer components sharing the default displayName
- Multiple versions of the same component loaded in development bundles
How to fix "Multiple components with the same displayName"
Open React DevTools and examine your component tree. Look for components that share identical names, especially those wrapped with memo, forwardRef, or HOCs.
Check your console for ESLint warnings if you have the react/display-name rule enabled:
# Install ESLint plugin if not already present
npm install --save-dev eslint-plugin-reactConfigure ESLint to detect missing displayNames:
{
"rules": {
"react/display-name": ["warn", {
"ignoreTranspilerName": false
}]
}
}For function components, assign displayName as a property:
const UserProfile = ({ user }) => {
return <div>{user.name}</div>;
};
// Add explicit displayName
UserProfile.displayName = 'UserProfile';
export default UserProfile;For anonymous components, provide both a name and displayName:
// Bad: Anonymous component
export default ({ user }) => <div>{user.name}</div>;
// Good: Named with displayName
const UserProfile = ({ user }) => <div>{user.name}</div>;
UserProfile.displayName = 'UserProfile';
export default UserProfile;When using React.memo, set displayName on the memoized component:
const ExpensiveComponent = ({ data }) => {
// Component logic
return <div>{data}</div>;
};
const MemoizedComponent = React.memo(ExpensiveComponent);
// Set displayName on the memoized version
MemoizedComponent.displayName = 'MemoizedExpensiveComponent';
export default MemoizedComponent;Or define it inline:
const MemoizedComponent = React.memo(
({ data }) => <div>{data}</div>
);
MemoizedComponent.displayName = 'ExpensiveComponent';React.forwardRef components need explicit displayName assignment:
const FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="fancy-button">
{props.children}
</button>
));
// Set displayName for debugging
FancyButton.displayName = 'FancyButton';
export default FancyButton;For combined memo and forwardRef:
const FancyInput = React.memo(
React.forwardRef((props, ref) => (
<input ref={ref} {...props} />
))
);
FancyInput.displayName = 'FancyInput';HOCs should generate unique displayNames based on the wrapped component:
function withAuth(WrappedComponent) {
const WithAuth = (props) => {
// HOC logic
return <WrappedComponent {...props} />;
};
// Generate unique displayName
const wrappedName = WrappedComponent.displayName
|| WrappedComponent.name
|| 'Component';
WithAuth.displayName = `withAuth(${wrappedName})`;
return WithAuth;
}
// Usage
const UserDashboard = ({ user }) => <div>{user.name}</div>;
UserDashboard.displayName = 'UserDashboard';
export default withAuth(UserDashboard);
// DevTools will show: withAuth(UserDashboard)Set displayName for Context.Provider and Context.Consumer:
import { createContext } from 'react';
const ThemeContext = createContext();
// Set displayName for debugging
ThemeContext.displayName = 'ThemeContext';
// Now Provider and Consumer will show as:
// ThemeContext.Provider and ThemeContext.Consumer
export default ThemeContext;For custom Context providers:
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
{children}
</ThemeContext.Provider>
);
}
ThemeProvider.displayName = 'ThemeProvider';If using styled-components, enable displayName in babel configuration:
{
"plugins": [
[
"babel-plugin-styled-components",
{
"displayName": true,
"fileName": true
}
]
]
}Or configure in next.config.js for Next.js:
module.exports = {
compiler: {
styledComponents: {
displayName: true,
fileName: true
}
}
};This automatically generates unique displayNames like "Button__StyledDiv" instead of generic "styled.div".
Advanced notes
Development vs Production: The displayName property is primarily useful in development. Most minification tools strip displayName in production builds to reduce bundle size. However, source maps can still help trace components back to their original names.
Performance Considerations: Setting displayName has negligible runtime performance impact. It's a static property assignment that only affects debugging tools, not rendering performance.
TypeScript Integration: When using TypeScript, you can type displayName explicitly:
const MyComponent: React.FC & { displayName?: string } = (props) => {
return <div>{props.children}</div>;
};
MyComponent.displayName = 'MyComponent';ESLint Configuration: The react/display-name rule has options to control behavior. Set "ignoreTranspilerName": false to enforce displayName even when the function name is inferred:
{
"rules": {
"react/display-name": ["warn", {
"ignoreTranspilerName": false,
"checkContextObjects": true
}]
}
}Debugging Tip: When you have duplicate displayNames and can't immediately fix them, use React DevTools' "Highlight updates" feature combined with component props inspection to differentiate instances by their unique prop values.
Component Naming Convention: Adopt a systematic naming pattern for wrapped components. For example: Original component "Button" becomes "MemoButton" when memoized, "ForwardRefButton" with forwardRef, or "withAuthButton" when wrapped in HOCs. This creates unique, descriptive names throughout your component tree.
Frequently asked questions
- What does "Multiple components with the same displayName" mean?
- The displayName property in React is a string used primarily for debugging purposes. React DevTools and other debugging tools use displayName to identify components in the component tree. When multiple components share the same displayName, it becomes challenging to differentiate between them during debugging sessions.
- How do I fix "Multiple components with the same displayName"?
- This debugging issue occurs when multiple React components share identical displayName values, making it difficult to distinguish between them in React DevTools. While not a runtime error, it creates confusion during development and debugging.
- What causes "Multiple components with the same displayName"?
- Using React.memo without setting a unique displayName on the wrapped component Higher-order components (HOCs) that wrap multiple components without generating unique displayNames React.forwardRef components lacking explicit displayName assignments
- Is the "Multiple components with the same displayName" error serious?
- It is a low-severity error โ more of a blocker than a risk. The steps above resolve it.