@babel/plugin-transform-react-display-name is a Babel transformation plugin that automatically adds displayName properties to React.createClass and createReactClass function calls. This enhances debugging and development experience by providing meaningful component names in React Developer Tools and error messages.
npm install --save-dev @babel/plugin-transform-react-display-nameThis is a Babel plugin, so it's not imported directly but configured in your Babel configuration:
{
"plugins": ["@babel/plugin-transform-react-display-name"]
}For programmatic usage with Babel API:
const babel = require("@babel/core");
const plugin = require("@babel/plugin-transform-react-display-name");
const result = babel.transform(code, {
plugins: [plugin]
});Internal Implementation Imports:
import { declare } from "@babel/helper-plugin-utils";
import { types as t } from "@babel/core";
import path from "node:path";The plugin automatically transforms React component definitions by adding displayName properties:
Input:
// Variable assignment
const MyComponent = React.createClass({
render() {
return <div>Hello</div>;
}
});
// createReactClass from standalone package
const AnotherComponent = createReactClass({
render() {
return <div>World</div>;
}
});Output:
const MyComponent = React.createClass({
displayName: "MyComponent",
render() {
return <div>Hello</div>;
}
});
const AnotherComponent = createReactClass({
displayName: "AnotherComponent",
render() {
return <div>World</div>;
}
});The main export is a standard Babel plugin function that returns a visitor object for transforming Abstract Syntax Trees (AST).
/**
* Default export Babel plugin function
* Created using @babel/helper-plugin-utils declare() function
* @param api - Babel plugin API with version assertion
* @returns Babel plugin object with visitor methods
*/
export default function(api: PluginAPI): PluginObject<PluginPass>;
interface PluginObject<State> {
name: string;
visitor: Visitor<State>;
}
interface Visitor<State = object> {
ExportDefaultDeclaration(path: NodePath<ExportDefaultDeclaration>, state: State & PluginPass): void;
CallExpression(path: NodePath<CallExpression>): void;
}
interface PluginAPI {
version: string;
assertVersion(range: number | string): void;
}
interface PluginPass {
filename?: string;
[key: string]: any;
}
interface NodePath<T = Node> {
node: T;
find(callback: (path: NodePath) => boolean | void): NodePath | undefined;
isAssignmentExpression(): boolean;
isObjectProperty(): boolean;
isVariableDeclarator(): boolean;
isStatement(): boolean;
}The plugin recognizes and transforms the following React component creation patterns:
React.createClass Calls:
// Variable declarations
var Component = React.createClass({});
let Component = React.createClass({});
const Component = React.createClass({});
// Assignment expressions
Component = React.createClass({});
this.Component = React.createClass({});
// Object properties
const exports = {
Component: React.createClass({})
};
// Export default
export default React.createClass({});createReactClass Calls:
// From create-react-class package
var Component = createReactClass({});
Component = createReactClass({});The plugin intelligently infers display names from various code patterns:
const UserProfile = React.createClass({});
// Result: displayName: "UserProfile"const components = {
Header: React.createClass({}),
Footer: React.createClass({})
};
// Results: displayName: "Header", displayName: "Footer"exports.Navigation = React.createClass({});
// Result: displayName: "Navigation"this.components.Sidebar = React.createClass({});
// Result: displayName: "Sidebar"// In file: UserCard.js
export default React.createClass({});
// Result: displayName: "UserCard"
// In file: components/index.js
export default React.createClass({});
// Result: displayName: "components" (parent directory name)The plugin includes built-in safety mechanisms:
// Input: Component already has displayName
const Component = React.createClass({
displayName: "CustomName",
render() { return null; }
});
// Output: No change - existing displayName preserved
const Component = React.createClass({
displayName: "CustomName",
render() { return null; }
});// Input: Component with spread properties
const Component = React.createClass({
...baseProps,
render() { return null; }
});
// Output: displayName added safely
const Component = React.createClass({
displayName: "Component",
...baseProps,
render() { return null; }
});The plugin only transforms calls that meet all criteria:
React.createClass or createReactClass callThe plugin uses several internal helper functions for validation:
/**
* Validates if a node is a React.createClass or createReactClass call
* @param node - AST node to validate
* @returns Type predicate indicating if node is a valid createClass call
*/
function isCreateClass(node?: Node): node is ReactCreateClassCall;
/**
* Adds displayName property to React.createClass call safely
* @param id - Display name string to add
* @param call - The createClass call expression to modify
*/
function addDisplayName(id: string, call: ReactCreateClassCall): void;
/**
* Built-in matcher for React.createClass member expressions
*/
const isCreateClassCallExpression: (node: any) => boolean;
/**
* Built-in validator for createReactClass identifier calls
* @param callee - Call expression callee to validate
* @returns Whether callee is createReactClass identifier
*/
const isCreateClassAddon: (callee: CallExpression["callee"]) => boolean;/**
* Internal type defining the shape of React.createClass call expressions
* Used for type safety in transformation logic
*/
type ReactCreateClassCall = CallExpression & {
arguments: [ObjectExpression];
};
/**
* AST Node types used in transformation
*/
interface Node {
type: string;
}
interface CallExpression extends Node {
type: "CallExpression";
callee: Expression;
arguments: (Expression | SpreadElement)[];
}
interface ObjectExpression extends Node {
type: "ObjectExpression";
properties: (ObjectProperty | ObjectMethod | SpreadElement)[];
}
interface ExportDefaultDeclaration extends Node {
type: "ExportDefaultDeclaration";
declaration: Expression | Declaration;
}
interface ObjectProperty extends Node {
type: "ObjectProperty";
key: Expression | Identifier | StringLiteral | NumericLiteral;
value: Expression;
computed: boolean;
}
interface Identifier extends Node {
type: "Identifier";
name: string;
}
interface StringLiteral extends Node {
type: "StringLiteral";
value: string;
}
interface SpreadElement extends Node {
type: "SpreadElement";
argument: Expression;
}
type Expression = CallExpression | ObjectExpression | Identifier | StringLiteral | any;
type Declaration = any;The plugin gracefully handles edge cases:
displayName properties are left unchangedNo exceptions are thrown during normal operation - invalid patterns are simply skipped.