display-name
display-name rule
display-name rule
Enforce component display names for better debugging experience. This rule is part of eslint-plugin-react-features and provides LLM-optimized error messages.
Quick Summary
| Aspect | Details |
|---|---|
| Severity | Warning (development) |
| Auto-Fix | โ No (requires manual naming) |
| Category | React |
| ESLint MCP | โ Optimized for ESLint MCP integration |
| Best For | React projects, debugging with React DevTools |
Rule Details
Why This Matters
| Issue | Impact | Solution |
|---|---|---|
| ๐ React DevTools | Anonymous components show as <Unknown> | Add displayName |
| ๐ Error Stack Traces | Hard to identify component | Named components |
| ๐ Performance Tools | Can't identify slow components | Clear naming |
| ๐งช Testing | Selectors may fail | Consistent names |
Configuration
This rule has no configuration options.
Examples
โ Incorrect
// Anonymous arrow function
const MyComponent = () => {
return <div>Hello</div>;
};
// Anonymous function expression
const AnotherComponent = function() {
return <div>World</div>;
};
// Class without displayName
class UserCard extends React.Component {
render() {
return <div>{this.props.name}</div>;
}
}
// HOC without displayName
const withAuth = (WrappedComponent) => {
return (props) => <WrappedComponent {...props} />; // โ No name
};โ Correct
MyComponentConfiguration Examples
Basic Usage
{
rules: {
'react-features/display-name': 'warn'
}
}Strict Mode
{
rules: {
'react-features/display-name': 'error'
}
}Common Patterns
Higher-Order Components
function withLogger(WrappedComponent) {
const WithLogger = (props) => {
console.log('Rendering:', WrappedComponent.displayName);
return <WrappedComponent {...props} />;
};
// Set displayName for debugging
WithLogger.displayName = `withLogger(${
WrappedComponent.displayName ||
WrappedComponent.name ||
'Component'
})`;
return WithLogger;
}React.forwardRef
const TextInput = React.forwardRef<HTMLInputElement, InputProps>(
(props, ref) => <input ref={ref} {...props} />
);
TextInput.displayName = 'TextInput';React.memo
const ExpensiveList = React.memo(({ items }) => {
return items.map(item => <Item key={item.id} {...item} />);
});
ExpensiveList.displayName = 'ExpensiveList';Context Components
const ThemeContext = React.createContext(defaultTheme);
const ThemeProvider = ({ children, theme }) => {
return (
<ThemeContext.Provider value={theme}>
{children}
</ThemeContext.Provider>
);
};
ThemeProvider.displayName = 'ThemeProvider';When Not To Use
| Scenario | Recommendation |
|---|---|
| ๐ Production builds | displayName is stripped in prod anyway |
| ๐งช Test utilities | May not need debugging names |
| ๐ฆ Tiny components | Named exports may be sufficient |
Comparison with Alternatives
| Feature | display-name | eslint-plugin-react | React DevTools |
|---|---|---|---|
| Class components | โ Yes | โ Yes | โ Shows name |
| Function components | โ Yes | โ Yes | โ ๏ธ May be Anonymous |
| HOCs | โ Enforces naming | โ ๏ธ Limited | โ Shows wrapper |
| LLM-Optimized | โ Yes | โ No | โ No |
| ESLint MCP | โ Optimized | โ No | โ No |
Related Rules
jsx-key- Enforce keys in listsreact-class-to-hooks- Migrate to hooks
Further Reading
- React displayName - Official React docs
- React DevTools - Debugging tools
- eslint-plugin-react display-name - React plugin docs
- ESLint MCP Setup - Enable AI assistant integration
Known False Negatives
The following patterns are not detected due to static analysis limitations:
Dynamic Variable References
Why: Static analysis cannot trace values stored in variables or passed through function parameters.
// โ NOT DETECTED - Prop from variable
const propValue = computedValue;
<Component prop={propValue} /> // Computation not analyzedMitigation: Implement runtime validation and review code manually. Consider using TypeScript branded types for validated inputs.
Imported Values
Why: When values come from imports, the rule cannot analyze their origin or construction.
// โ NOT DETECTED - Value from import
import { getValue } from './helpers';
processValue(getValue()); // Cross-file not trackedMitigation: Ensure imported values follow the same constraints. Use TypeScript for type safety.
Not a finding
React reads a component's display name off Function.name or Class.name. A component
with a name is already named โ there is nothing to fix and nothing to report.
| Code | Why it is silent |
|---|---|
function Profile() { ... } | Named by the function. |
const Profile = () => ... | Named by the binding. |
class Profile extends Component { ... } | Named by the class; static displayName is optional. |
const Row = memo(() => <div />) | The binding names the component through the wrapper. |
If it fires, React genuinely cannot name it: an anonymous export default, an
anonymous class component, or memo/forwardRef with no binding to take a name from.
Those render as Anonymous in DevTools and in every component stack trace.
Did this rule catch something? Star the repo to get new CWE coverage as we ship it โ or follow the AI-code-security benchmarks behind these rules.