关于 typescript-react
用于在 React 任务中应用 TypeScript Style Guide 规范的技能。它指导组件结构、属性、状态与数据流,同时遵循项目仓库的现有做法。
主要功能
- 01优先检查仓库规范
- 02容器与 UI 组件指导
- 03属性与状态建议
- 04URL 与全局状态指导
- 05数据获取边界
适用场景
- 01组织 React 功能与组件结构
- 02审查属性转状态的模式
- 03确定应用状态的存放位置
- 04规划功能中的数据获取
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mkosir/ typescript-style-guide --skill typescript-react安装后在 Claude Code 中输入/typescript-react确认已加载。
详细介绍
React
在当前任务的上下文中,遵循 TypeScript 风格指南中的 React 约定。
工作流
- 检查使用方仓库中关于 React、框架和状态管理的约定。
- 以仓库中明确的约定为准,优先于这份主观指南。
- 仅应用、审查或说明与任务相关的指导。
- 当组件或状态设计取决于应用上下文时,说明重要的权衡。
边界
- 让 TypeScript、React 和 ESLint 负责它们能自动执行的检查。
- 不要仅仅因为启用了此技能,就重新设计无关的组件或状态。
相关指导
函数
如需详细的函数设计指导,请在可用时使用 typescript-functions。
附录 - React
由于 React 组件和钩子也是函数,因此同样适用函数约定。
Props 转状态
一般而言,应避免将 props 用作初始状态,因为 props 变化时状态不会更新。这可能导致难以追踪的错误、意外的副作用以及测试困难。
如果确实存在将 prop 用作初始状态的场景,该 prop 必须以 initial 为前缀(例如 initialProduct、initialSort 等)。
// ❌ Avoid using props to state
type FooProps = {
productName: string;
userId: string;
};
export const Foo = ({ productName, userId }: FooProps) => {
const [productName, setProductName] = useState(productName);
...
// ✅ Use prop prefix `initial` when there is a rationale for it
type FooProps = {
initialProductName: string;
userId: string;
};
export const Foo = ({ initialProductName, userId }: FooProps) => {
const [productName, setProductName] = useState(initialProductName);
...
Props 类型
// ❌ Avoid using React.FC type
type FooProps = {
name: string;
score: number;
};
export const Foo: React.FC<FooProps> = ({ name, score }) => {
// ✅ Use props argument with type
type FooProps = {
name: string;
score: number;
};
export const Foo = ({ name, score }: FooProps) => {...
组件类型
容器
- 所有容器组件都以 "Container" 或 "Page" 为后缀:
[ComponentName]Container|Page。使用 "Page" 后缀表示该组件是真正的网页。 - 每个功能都有一个容器组件(例如
AddUserContainer.tsx、EditProductContainer.tsx、ProductsPage.tsx)。 - 包含业务逻辑。
- API 集成。
- 结构:
ProductsPage/ ├─ api/ │ └─ useGetProducts/ ├─ components/ │ └─ ProductItem/ ├─ utils/ │ └─ filterProductsByType/ └─ index.tsx
UI - 功能
- 用于满足功能需求的表现型组件。
- 嵌套在容器组件文件夹中。
- 应尽可能遵循函数约定。
- 不进行 API 集成。
- 结构:
ProductItem/ ├─ index.tsx ├─ ProductItem.stories.tsx └─ ProductItem.test.tsx
UI - 设计系统
- 在整个代码库中使用的全局可复用或共享组件。
- 结构:
Button/ ├─ index.tsx ├─ Button.stories.tsx └─ Button.test.tsx
存储和传递数据
-
仅向子组件传递必要的 props,不要传递整个对象。
-
善用 URL 存储状态,尤其是筛选、排序等状态。
-
不要将 URL 状态与本地状态同步。
-
考虑通过 props、URL 或组合子组件来简单地传递数据。将全局状态(Zustand、Context)作为最后手段。
-
当组件需要归属并协同工作时,使用 React 复合组件:
menu、accordion、navigation、tabs、list等。
始终按以下方式导出复合组件:// PriceList.tsx const PriceListRoot = ({ children }) => <ul>{children}</ul>; const PriceListItem = ({ title, amount }) => <li>Name: {name} - Amount: {amount}<li/>; // ❌ export const PriceList = { Container: PriceListRoot, Item: PriceListItem, }; // ❌ PriceList.Item = Item; export default PriceList; // ✅ export const PriceList = PriceListRoot as typeof PriceListRoot & { Item: typeof PriceListItem; }; PriceList.Item = PriceListItem; // App.tsx import { PriceList } from "./PriceList"; <PriceList> <PriceList.Item title="Item 1" amount={8} /> <PriceList.Item title="Item 2" amount={12} /> </PriceList>; -
UI 组件只应展示派生状态并发送事件,不应做其他事情(不包含业务逻辑)。
-
与许多编程语言一样,函数参数可以传递给下一个函数,再继续传递下去。
React 组件也不例外,因此不必担心 props 层层传递。
如果随着应用扩展,props 层层传递确实成为问题,可尝试重构渲染方法或父组件中的本地状态,或使用组合。 -
仅允许在容器组件中获取数据。
-
鼓励使用服务端状态库(TanStack Query、Apollo Client 等)。
-
不建议使用客户端状态库管理全局状态。
重新考虑某个状态是否确实需要在整个应用中全局共享,例如themeMode或Permissions,或者它能否存储为服务端状态(例如来自/me端点的用户设置)。如果确实仍需要全局状态,请使用 Zustand 或 Context。