AgentSkillsCN

create-component-react

创建可复用 React 组件的实践指南,涵盖 props 与类型约定、无状态原则、类名合并(clsx)、原生属性透传以及导出规范,并附上示例实现。

SKILL.md
--- frontmatter
name: create-component-react
description: "创建可复用的 React 组件实践指南,涵盖 props 与类型约定、无状态原则、类名合并(clsx)、原生属性透传及导出规范,附示例实现。"

新组件实践指南(中文)——创建组件

本次示例涉及的文件

  • packages/camphora-react/src/components/<Component>/index.tsx —— 简洁的 React 包装组件,组合类并透传原生属性。
  • packages/camphora-react/src/components/index.ts —— 将组件导出,供项目其他地方直接引用。

可复用步骤(组件部分) 2. 编写 React 组件 - 在 packages/camphora-react/src/components/<Component>/index.tsx 中创建组件。 - 组件约定: - 默认导出 <Component> 函数组件。 - 接受 PropsWithChildren<React.DivHTMLAttributes<HTMLDivElement>>,以便透传 onClickdisabledaria-* 等原生属性。 - 组件的 props 应在组件内展开(spread)并透传到原生元素,确保 aria-*onClickdisabled 等原生属性被保留(例如使用 {...rest})。 - 组件的 props 类型应通过接口定义,并使用 I 前缀命名,例如 interface I<Component>Props extends React.DivHTMLAttributes<HTMLDivElement> {};组件应使用该接口进行类型注解。 - 使用 clsx 将外部 className 与基础 <component> 类合并;不引入变体类型的 props(例如 variant="primary")——所有视觉变体通过类名控制。 - 示例实现:

code
	 ```tsx
	 import React from "react";
	 import { <component> } from "@idealjs/camphora-styled";
	 import clsx from "clsx";

	 interface I<Component>Props extends React.DivHTMLAttributes<HTMLDivElement> {}

	 const <Component>: React.FC<I<Component>Props> = ({ children, className, ...rest }) => (
		 <div className={clsx(<component>, className)} {...rest}>
			 {children}
		 </div>
	 );

	 export default <Component>;
	 ```

3. 导出组件 - 在 packages/camphora-react/src/components/index.ts 中添加导出项,使其他包可直接通过 @idealjs/camphora-react 引入。

注意与约定

  • 使用 clsx 合并类名。
  • 组件层尽量减少自定义 props,把视觉与主题相关的变化交给 token 与类名。
  • 若组件需要状态(例如打开/关闭),可以使用真实的 DOM 输入或内部状态实现,但仍建议把视觉状态由类名控制。

组件状态约定

  • 组件应保持无状态(stateless)。若组件需要 UI 状态(例如 visible / 打开-关闭),应由外部通过 props 传入并由外部控制(例如传入 visibleonClose),组件内部不应持有 UI 可变状态。
  • 这里的“组件内部不应持有 UI 可变状态”明确指不得在组件内部使用 React Hook 来管理可变的 UI 状态,例如不得使用 useStateuseReduceruseRef(用于保存可变 UI 状态)、useEffect(用于在组件内维持状态相关副作用)等来保存或控制显示/打开-关闭等 UI 行为。若需要状态,请采用受控模式(由父组件通过 props + 回调,如 value/onChangevisible/onClose)来管理。