React 官方和社区推荐的组件命名遵循以下规范:
PascalCase(大驼峰式命名):所有单词首字母大写
UserProfile
userProfile
(小驼峰,适用于实例)user_profile
(下划线)语义化命名:名称应明确表达组件用途
PrimaryButton
Button1
与文件同名:组件文件应与默认导出组件同名
// UserCard.jsx
export default function UserCard() { ... }
目录命名:组件目录使用 PascalCase
/components
/UserProfile
/Avatar
Avatar.jsx
Avatar.css
组件类型 | 命名约定 | 示例 |
---|---|---|
普通组件 | PascalCase | UserList |
高阶组件(HOC) | 前缀 with |
withAuth |
容器组件 | 后缀 Container |
ProfileContainer |
布局组件 | 前缀 Layout |
LayoutMain |
路由组件 | 后缀 Page |
HomePage |
UI 工具组件 | 前缀 UI |
UIModal |
上下文提供者 | 后缀 Provider |
ThemeProvider |
推荐写法:
// components/UserProfile/Avatar.jsx
function Avatar({ src, alt }) {
return
;
}
export default Avatar;
不推荐写法:
// components/userProfile/avatar.jsx
const avatar = ({ src, alt }) => (
);
export default avatar;
displayName
是 React 组件的一个静态属性,用于定义组件在开发者工具中的显示名称:
function MyComponent() {
return Hello;
}
MyComponent.displayName = 'CustomDisplayName';
现代工具自动推断名称
displayName
会造成冗余函数组件名称更可靠
// 现代React推荐 - 名称自动可用
function UserProfile() { ... }
// 不再需要
UserProfile.displayName = 'UserProfile';
类组件使用频率降低
displayName
TypeScript 的增强支持
displayName
配置维护负担
ES6 命名函数
// 推荐 ✅
export default function Header() { ... }
// 不推荐 ❌
const Header = () => { ... };
Header.displayName = 'Header';
Babel 插件配置
// babel.config.js
module.exports = {
presets: [
['@babel/preset-react', {
runtime: 'automatic',
development: process.env.NODE_ENV === 'development'
}]
]
};
构建工具优化
optimization.concatenateModules
对于需要动态生成的组件,可使用:
function createDynamicComponent(type) {
const Component = () => { ... };
// 必要时才使用 displayName
Component.displayName = `Dynamic${type}`;
return Component;
}
HOC 应自动设置被包装组件的名称:
function withLogging(WrappedComponent) {
function WithLogging(props) {
// ...增强逻辑
return ;
}
// 自动继承名称
WithLogging.displayName = `WithLogging(${getDisplayName(WrappedComponent)})`;
return WithLogging;
}
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
避免匿名函数创建组件:
// ❌ 不推荐 - React DevTools 显示为 "Anonymous"
export default () => Hello;
// ✅ 推荐 - 显示明确名称
export default function Greeting() {
return Hello;
}
大型项目可采用命名空间组织组件:
// components/User/index.js
export { default as Avatar } from './Avatar';
export { default as Profile } from './Profile';
// 使用时
import { User } from 'components';
确保测试描述与组件命名一致:
describe('UserProfile Component', () => {
it('renders avatar image', () => { ... });
});
利用 JSDoc 增强可维护性:
/**
* 用户头像组件
* @param {Object} props - 组件属性
* @param {string} props.src - 图片URL
* @param {string} props.alt - 替代文本
*/
export default function Avatar({ src, alt }) {
return
;
}
.eslintrc.js
推荐配置:
module.exports = {
rules: {
'react/display-name': ['error', {
ignoreTranspilerName: true // 信任编译工具保留名称
}],
'react/jsx-pascal-case': ['error', {
allowAllCaps: true, // 允许全大写缩写如 SVG
ignore: [] // 无例外
}]
}
};
tsconfig.json
配置建议:
{
"compilerOptions": {
"jsx": "react-jsx",
"preserveConstEnums": true,
"stripInternal": false
}
}
良好命名:
Component Tree:
└─ App
├─ Header
└─ UserProfile
├─ Avatar
└─ ProfileInfo
匿名组件:
Component Tree:
└─ Unknown
├─ Unknown
└─ Unknown
├─ Unknown
└─ Unknown
查找项目中所有 displayName
使用
grep -r "displayName" src/
逐步替换为命名函数
// 迁移前
const Button = (props) => { ... };
Button.displayName = 'Button';
// 迁移后
function Button(props) { ... }
更新测试用例
使用 jscodeshift 转换:
// transform.js
export default function transformer(file, api) {
const j = api.jscodeshift;
return j(file.source)
.find(j.AssignmentExpression, {
left: {
object: { type: 'Identifier' },
property: { name: 'displayName' }
}
})
.remove()
.toSource();
}
/src
/components
/User
UserProfile.jsx # 主组件
UserAvatar.jsx # 子组件
index.js # 统一导出
/containers
UserContainer.jsx # 容器组件
/hocs
withAuth.js # 高阶组件
通过遵循这些规范,可以构建出更可维护、更易调试的 React 应用,同时避免过时的 displayName
使用模式。