AgentSkillsCN

Refactoring Monolithic Pages

系统化地指导您如何将大型复杂页面拆解为可管理、相互独立的组件。

SKILL.md
--- frontmatter
name: Refactoring Monolithic Pages
description: A systematic guide to breaking down large, complex pages into manageable, independent components.

Refactoring Monolithic Pages

This skill outlines the standard operating procedure for decomposing large React pages (1000+ lines) into clean, maintainable component hierarchies. This process enhances readability, reduces cognitive load, and isolates complexity.

The "Extract & Glue" Protocol

1. Audit & Identify logical Sections

Scan the monolithic file (page.tsx) and identify distinct UI sections. Look for:

  • Visual Boundaries: Cards, Panels, Modals, Lists.
  • Functional Boundaries: Chat interfaces, Status displays, Forms.
  • Comment Blocks: Often developers leave comments like // Chat Section or // Verification Modal. These are natural cut-points.

2. The Extraction Strategy

For each identified section, create a new component file.

A. Analyze Dependencies

Before cutting code, determine what data the section needs:

  • Props: What primitive values (IDs, strings) does it rely on?
  • State: Does it use useState? Is that state local (only used here) or shared?
  • Server Data: Does it rely on useQuery data?

B. Component Classification

Decide on the component type:

  • Smart Container: Fetches its own data given an ID. Best for independence.
  • Presentation Component: Purely receives data via props. Best for reusability.
  • Hybrid: Receives some data, manages its own ephemeral UI state.

3. Move Logic, Not Just JSX

Don't just copy the JSX. Move the brain too.

  • Formatting Functions: Move helpers like formatLabel or getPhase into the component or a shared utility file.
  • Event Handlers: Move handleSave, handleDelete functions into the component.
  • Effects: Move useEffect logic unrelated to the parent into the child.

4. State Management Migration RULES

  • Local UI State: Move useState into the child component. (e.g., isExpanded, editingId).
  • Server State: ideally, pass the ID and letting the child use the same React Query hook. React Query deduplicates requests, so this is efficient and prevents prop drilling.
  • Shared State: If two siblings need to talk, keep the state in the parent or use a lightweight Context/Zustand store (see client-state-standards skill).

5. "Glue" The Parent

The original page should become a Layout Orchestrator. Its job is effectively reduced to:

  1. Reading URL params.
  2. Handling high-level page state (like "loading" or "404").
  3. Rendering a clean JSX tree of child components.

Before:

tsx
// page.tsx (1000 lines)
export default function Page() {
  const [msg, setMsg] = useState("");
  const { data } = useQuery(...);
  // ... 500 lines of logic ...
  return (
    <div>
      {/* 200 lines of Chat JSX */}
      {/* 200 lines of List JSX */}
    </div>
  )
}

After:

tsx
// page.tsx (150 lines)
export default function Page() {
  const { id } = useParams();
  return (
    <div className="grid gap-4">
      <StatusCard applicationId={id} />
      <div className="grid grid-cols-2">
        <ChatInterface applicationId={id} />
        <TaskRoadmap applicationId={id} />
      </div>
    </div>
  )
}

Validation Checklist

  1. Zero Prop Drilling: Are you passing data down 3+ levels? If so, pass the ID and fetch data lower down.
  2. Single Responsibility: Does the parent file contain logic that only pertains to one specific child? If yes, move it down.
  3. Clean Imports: Does the parent import specific UI libraries (buttons, icons) that are only used in one section? Move them.