Skip to content
Development
Skill

/eisland-dev-refactor-module-split

Refactor a monolithic React component file into a standardized module structure with components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file into subdirectories,

From plugin
eisland
27915 skills7 commands
Install
$ npx -y skills add JNTMTMTM/eIsland --skill eisland-dev-refactor-module-split --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/eisland-dev-refactor-module-split

Context preview

The summary Claude sees to decide when to auto-load this skill.

Refactor a monolithic React component file into a standardized module structure with components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file into subdirectories,

SKILL.md

eisland-dev-refactor-module-split.SKILL.md
name: eisland-dev-refactor-module-split
author: JNTMTMTM
description: >
  Refactor a monolithic React component file into a standardized module structure with
  components/, hooks/, utils/, types/, and config/ subdirectories. Use this skill whenever
  the user asks to "split", "refactor", "拆分", "拆解", or "restructure" a component file
  into subdirectories, or when they mention organizing code into modules.

Refactor Module Split

Split a monolithic React component file into a clean module structure with five subdirectories: `components/`, `hooks/`, `utils/`, `types/`, and `config/`, plus an `index.ts` entry point.

When to use

  • A single `.tsx` file has grown large and contains multiple concerns (utility functions, hooks, sub-components, constants, type definitions)
  • The user explicitly asks to split/refactor a component into subdirectories
  • The file is a React component that mixes UI rendering, state management, utility logic, and configuration

Process

Step 0: Ensure module scaffolding exists

Before extracting any code, verify the target module directory has the required structure. If any of the following are missing, create them first:

<module>/
├── index.ts          (if missing, create with placeholder export)
├── types/            (if missing, create directory)
├── config/           (if missing, create directory)
├── utils/            (if missing, create directory)
├── hooks/            (if missing, create directory)
└── components/       (if missing, create directory)
  • Empty directories should contain a `.gitkeep` placeholder
  • `index.ts` should initially export the original component (update after refactoring)

Step 1: Analyze the source file

Read the target file in full. Categorize every piece of code into one of five buckets:

| Bucket | Criteria | Target directory | |--------|----------|-----------------| | **Types** | `type`, `interface`, component prop interfaces, hook return types | `types/` | | **Constants** | `const` values, config keys, store keys, i18n keys/defaults | `config/` | | **Pure functions** | No React hooks, no side effects, deterministic input→output | `utils/` | | **React hooks** | Uses `useState`, `useEffect`, `useMemo`, `useCallback`, or custom hooks | `hooks/` | | **Sub-components** | Returns JSX, used within the main component | `components/` |

Also check if the file's sibling directories already exist (e.g., `components/` or `hooks/` may already have files from prior refactoring). Don't duplicate existing extractions.

Step 2: Create the extracted files

For each extracted piece, create a new file in the appropriate directory. Every file must include:

1. **License header** — copy the exact GPL-3.0 block from the source file 2. **File-level JSDoc** — `@file`, `@description`, `@author` tags 3. **Function/type JSDoc** — `@param`, `@returns` for all exported functions 4. **Correct imports** — relative paths back to shared types or store slices

Naming conventions:

  • `types/` — camelCase with module prefix (e.g., `todoTypes.ts`, `albumTypes.ts`, `localFileSearchTypes.ts`)
  • `config/` — camelCase with module prefix (e.g., `todoConfig.ts`, `albumConfig.ts`, `localFileSearchConfig.ts`)
  • `utils/` — camelCase with module prefix (e.g., `todoUtils.ts`, `albumUtils.ts`, `localFileSearchUtils.ts`)
  • `hooks/` — camelCase with `use` prefix (e.g., `useTodos.ts`, `useAlbumItems.ts`, `useLocalFileSearch.ts`)
  • `components/` — PascalCase component name (e.g., `TodoTab.tsx`, `TodoHeader.tsx`, `AlbumGridItem.tsx`)

Step 3: Define types first

Create `types/<module>Types.ts` **before** other files. This file must contain:

1. **Domain types** — data models, enums, union types used by the module 2. **Hook return type** — `Use<Module>Return` interface describing the hook's full return shape 3. **Component prop interfaces** — `<Component>Props` for every sub-component

All component prop interfaces and hook return types MUST be defined in `types/`, not inline in component or hook files.

Example pattern:

// types/todoTypes.ts

/** 紧急程度 */
export type Priority = 'P0' | 'P1' | 'P2';

/** 单条待办 */
export interface TodoItem { ... }

/** useTodos hook 返回值类型 */
export interface UseTodosReturn { ... }

/** TodoHeader 组件入参 */
export interface TodoHeaderProps { ... }

/** TodoInputBar 组件入参 */
export interface TodoInputBarProps { ... }

Step 4: Rewrite the source file

Replace the extracted code in the original file with imports from the new modules. The source file should become a thin composition layer that:

  • Imports hook from `../hooks/use<Module>`
  • Imports sub-components from `./<ComponentName>`
  • Calls the hook at the top level
  • Destructures hook return values and passes them as props to sub-components
  • Contains no extracted logic, no `useEffect`, no utility functions

Step 5: Create the index.ts entry point

Create `<module>/index.ts` that re-exports the main component:

export { TodoTab } from './components/TodoTab';

Step 6: Verify

Run these checks in order — all must pass before committing:

# 1. TypeScript compilation
npx tsc --noEmit --pretty

# 2. Comment standards compliance (file headers, JSDoc)
npm run comment:check

# 3. i18n completeness (all t() keys exist in both zh-CN and en-US)
npm run i18n:check

# 4. Unit tests
npm run test

If any check fails, fix the issue before proceeding. Common failures:

  • `comment:check` — missing license header, missing `@file`/`@description`/`@author`, missing JSDoc on exported functions
  • `i18n:check` — a `t('key')` call references a key not present in both locale files
  • `test` — a refactored import path broke a test, or an extracted function changed behavior

Step 7: Commit

Use a conventional commit message:

refactor(<module-name>): extract types, utils, hooks, components, config from <OriginalFile>

- types/<name>Types.ts: type definitions + component prop interfaces
- utils/<name>Utils.ts: <what it does>
- hooks/us
Read more
Ships witheisland

eIsland - A sleek, Apple Dynamic Island inspired floating widget for Windows, built with Electron.

Get the whole plugin

Other skills on eisland.