Skip to content

React 规范

学习地址

基本规则

  1. 每个文件只包含一个 React 组件,但允许多个无状态组件存在于同一文件
  2. 始终使用 JSX 语法,不要使用 React.createElement
  3. 推荐使用函数组件 + Hooks,避免使用 Class 组件

项目结构

src
├── api                  接口管理
│   └── 业务模块.ts
├── assets               静态资源
│   ├── images
│   └── styles
├── components           公共组件
│   └── CompName
│       ├── index.tsx
│       └── index.module.scss
├── hooks                自定义 Hooks
│   └── useXxx.ts
├── pages / views        页面组件
│   └── PageName
│       ├── index.tsx
│       ├── index.module.scss
│       └── components   页面私有组件
├── router               路由配置
│   └── index.tsx
├── store                状态管理
│   ├── index.ts
│   └── modules
├── utils                工具函数
│   └── request.ts
├── types                类型定义
│   └── index.d.ts
├── App.tsx
└── main.tsx

组件命名

  • 组件文件:使用 PascalCase(大驼峰),如 UserProfile.tsx
  • 组件目录:使用 PascalCase,如 UserProfile/index.tsx
  • 组件实例:使用 camelCase(小驼峰),如 const userProfile = <UserProfile />
tsx
// 推荐
import UserProfile from "./UserProfile";

// 不推荐
import userProfile from "./UserProfile";
import User_Profile from "./User_Profile";

JSX 规范

标签与缩进

tsx
// 推荐:多行 JSX 用括号包裹
return (
  <div className="container">
    <Header />
    <Main />
  </div>
);

// 不推荐
return (
  <div className="container">
    <Header />
    <Main />
  </div>
);

属性规范

  1. 属性使用 camelCase
  2. 属性值为 true 时可省略值
  3. 使用双引号给 JSX 属性值,使用单引号给 JS 代码
tsx
// 推荐
<Input type="text" disabled onChange={handleChange} />

// 不推荐
<Input type='text' disabled={true} onChange={handleChange} />
  1. 属性较多时换行书写,每个属性占一行
tsx
// 推荐
<UserProfile
  className="user-profile"
  name={userName}
  age={userAge}
  onEdit={handleEdit}
/>

// 不推荐
<UserProfile className="user-profile" name={userName} age={userAge} onEdit={handleEdit} />

Key 属性

列表渲染必须添加唯一的 key,禁止使用数组索引作为 key

tsx
// 推荐
{
  list.map((item) => <ListItem key={item.id} data={item} />);
}

// 不推荐
{
  list.map((item, index) => <ListItem key={index} data={item} />);
}

Hooks 规范

基本原则

  1. 只在函数组件的最顶层调用 Hooks,不要在循环、条件或嵌套函数中调用
  2. 只在 React 函数组件或自定义 Hooks 中调用 Hooks
  3. 自定义 Hooks 必须以 use 开头命名
tsx
// 推荐
function useUserInfo(userId: string) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser(userId).then(setUser);
  }, [userId]);

  return user;
}

// 不推荐:没有以 use 开头
function getUserInfo(userId: string) {
  const [user, setUser] = useState(null);
  // ...
}

useEffect 使用规范

  1. 必须正确声明依赖项数组
  2. 有副作用清理需求时,返回清理函数
  3. 避免在 useEffect 中直接修改 DOM
tsx
// 推荐
useEffect(() => {
  const timer = setInterval(() => {
    setCount((c) => c + 1);
  }, 1000);

  return () => clearInterval(timer); // 清理副作用
}, []);

// 不推荐:缺少依赖项 / 缺少清理
useEffect(() => {
  setInterval(() => {
    setCount(count + 1);
  }, 1000);
});

useState 使用规范

tsx
// 推荐:语义化命名
const [isLoading, setIsLoading] = useState(false);
const [userList, setUserList] = useState<User[]>([]);

// 不推荐
const [flag, setFlag] = useState(false);
const [data, setData] = useState([]);

事件处理

  1. 事件处理函数以 handle 开头命名
  2. 传递给子组件的回调以 on 开头命名
tsx
// 父组件
function ParentComponent() {
  const handleItemClick = (id: string) => {
    // 处理点击
  };

  return <ChildComponent onItemClick={handleItemClick} />;
}

// 子组件
interface ChildProps {
  onItemClick: (id: string) => void;
}

function ChildComponent({ onItemClick }: ChildProps) {
  return <div onClick={() => onItemClick("1")}>Click me</div>;
}

TypeScript 规范

  1. 组件 Props 使用 interface 定义,以 Props 结尾
  2. 导出类型使用 typeinterface
  3. 避免使用 any,尽量使用明确的类型
tsx
// 推荐
interface UserCardProps {
  name: string;
  age: number;
  avatar?: string;
  onEdit: (id: string) => void;
}

function UserCard({ name, age, avatar, onEdit }: UserCardProps) {
  return (
    <div className="user-card">
      {avatar && <img src={avatar} alt={name} />}
      <span>{name}</span>
      <span>{age}</span>
    </div>
  );
}

// 不推荐
function UserCard(props: any) {
  return <div>{props.name}</div>;
}

状态管理

推荐使用以下状态管理方案(按项目复杂度选择):

方案适用场景
useState / useReducer组件内部简单状态
Context API少量全局共享状态
Zustand中小型项目全局状态管理
Redux Toolkit大型复杂项目

性能优化

  1. React.memo:对纯展示组件使用 React.memo 避免不必要的重渲染
  2. useMemo / useCallback:缓存计算结果和回调函数
  3. 懒加载:使用 React.lazy + Suspense 实现路由懒加载
tsx
// 路由懒加载
const UserPage = React.lazy(() => import("./pages/User"));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <UserPage />
    </Suspense>
  );
}
  1. 避免在渲染中创建新对象/函数
tsx
// 推荐
const style = useMemo(() => ({ color: 'red', fontSize: 14 }), [])

// 不推荐:每次渲染都创建新对象
<div style={{ color: 'red', fontSize: 14 }} />