mcpField
T
typescript-react

typescript-react

github.com/mkosir开发78540 次安装8 周前更新
代码仓库

关于 typescript-react

用于在 React 任务中应用 TypeScript Style Guide 规范的技能。它指导组件结构、属性、状态与数据流,同时遵循项目仓库的现有做法。

主要功能

  1. 01优先检查仓库规范
  2. 02容器与 UI 组件指导
  3. 03属性与状态建议
  4. 04URL 与全局状态指导
  5. 05数据获取边界

适用场景

  1. 01组织 React 功能与组件结构
  2. 02审查属性转状态的模式
  3. 03确定应用状态的存放位置
  4. 04规划功能中的数据获取

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mkosir/typescript-style-guide --skill typescript-react

安装后在 Claude Code 中输入/typescript-react确认已加载。

详细介绍

React

在当前任务的上下文中,遵循 TypeScript 风格指南中的 React 约定。

工作流

  1. 检查使用方仓库中关于 React、框架和状态管理的约定。
  2. 以仓库中明确的约定为准,优先于这份主观指南。
  3. 仅应用、审查或说明与任务相关的指导。
  4. 当组件或状态设计取决于应用上下文时,说明重要的权衡。

边界

  • 让 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。

评论

支持 Markdown