React

Verified against Claude Code · 2026-07-21

Break a 600-line component into a maintainable tree

Splits an overgrown component along its actual seams — data, layout, and interaction — instead of by line count, and flags where the split reveals a real prop-drilling or context problem instead of hiding it.

Claude CodeCursorGitHub Copilot ChatClaude4 fillable variables

The prompt

Ready to copy — highlighted parts are example details you can swap.

You are refactoring an overgrown React component into a tree of smaller components, without changing what the user sees or how the component behaves. This is a structural refactor, not a rewrite — every piece of existing logic keeps its current behavior unless a bug is named explicitly.

COMPONENT
A 640-line AccountDashboard component that fetches account data, renders a filter bar, a stats grid, a sortable data table, and an edit-row modal, all in one file.

CURRENT RESPONSIBILITIES
Fetches account data on mount, renders a filter bar with three dropdowns, renders a stats summary row, renders a sortable table with pagination, opens an edit modal per row, and handles the save request and its error state.

WHY THIS NEEDS TO SPLIT NOW
Two engineers hit merge conflicts in this file three times last sprint because unrelated features (the filter bar and the edit modal) both touch it.

SHARED STATE NOTES
selectedRowId and the edit-modal open/close flag are the only two pieces of state read by more than one section; everything else is local to a single visual area.

DECOMPOSITION RULES
Split along actual seams, not line count or an arbitrary target size: a data-fetching concern, a piece of layout that repeats or could stand alone, a self-contained interactive widget such as a dropdown, a modal, or a form section. Every new component needs a name that describes what it renders, never "PartOne" or "Section2" or "DashboardInner". State stays as close to where it is used as possible — only lift state to a parent when two or more of the new children genuinely need to read or write it, not preemptively "in case a future feature needs it." Pass data down as typed props with names that describe the data itself, not generic names like data, config, or props. If two extracted components end up needing five or more props in common, that is a signal they should be one component, or that the shared props belong in a scoped context — say so explicitly in your output rather than silently implementing either fix without flagging it. Decide file layout by reuse boundary, not by a blanket one-component-per-file rule: a small subcomponent that is only ever rendered by its immediate parent and will never plausibly be imported elsewhere can live in the same file as that parent, while a component with a broader potential reuse boundary — even if nothing reuses it yet — should get its own file so it does not carry the parent's unrelated imports along with it.

WHAT NOT TO CHANGE
Do not rename existing event handlers, change existing prop names on components that stay intact, reformat code you did not need to touch, or introduce a new state-management library as part of this pass — that is a separate decision, not a side effect of a decomposition.

OUTPUT FORMAT
1. A one-paragraph plan: the new component tree, named, with a one-line reason for each split.
2. The extracted components, each in its own code block, with typed props.
3. The original component, now composing the new pieces and holding only the state that genuinely could not be pushed down.
4. Anything you noticed that violates the five-shared-props rule above, even if you did not act on it, plus any other coupling you spotted but left alone because fixing it was out of scope for this pass.

Customize

Optional — swap in your own details for the highlighted parts above.

Why this works

Splitting along "seams" — data-fetching, repeated layout, self-contained widgets — instead of a line-count target is what prevents the common bad outcome of a decomposition that produces several equally arbitrary chunks with no independent reason to exist, each still coupled to the others through five different props because the split never asked what actually varies independently. The rule against lifting state preemptively directly targets the most common overcorrection that follows a god-component review: once a component is flagged as "too big," the reflex is to lift everything to a shared parent to be safe, which just recreates the exact same prop-drilling problem one level higher in the tree instead of fixing it. The five-shared-props heuristic gives the model a concrete, countable trigger for "this split created a coupling problem" instead of a vague appeal to judgment, so it has to notice and report a real signal rather than silently produce one and call the job done. Explicitly forbidding renamed handlers, reformatted untouched code, and a smuggled-in state-management library keeps the diff reviewable — the single biggest reason engineers distrust an AI-generated refactor is a diff three times larger than the actual structural change, where the real edit is buried under unrelated churn a reviewer now has to comb through line by line. The file-layout guidance — co-locating a genuinely single-use subcomponent instead of mechanically giving every extracted piece its own file — targets a secondary but real cost of automated decomposition: a reviewer opening a pull request with eight new files for one component split has to context-switch eight times to understand a single change, and most of those files will only ever be imported from the one parent that was just split, so the extra file boundary buys nothing beyond navigation friction. Treating file layout as a judgment call tied to an actual reuse boundary, rather than a fixed one-file-per-component convention, keeps the decomposition proportional to what the component tree actually needs rather than to a rule that looks tidy on one PR but adds real navigation cost across dozens of components over a codebase's lifetime.

What you get back

Plan: split AccountDashboard into FilterBar (filter state + controls), AccountStatsRow (pure display of summary numbers), AccountTable (sorting, pagination, row selection), and EditAccountModal (its own open/close state, receiving the selected account as a prop). Data fetching stays in AccountDashboard since only it and AccountTable need the raw list — passed down as a typed accounts: Account[] prop. Flag: AccountTable and EditAccountModal share six props (account, onSave, onClose, isOpen, errors, isSaving) — recommend either merging them into one AccountRowEditor component, or lifting those six into a small scoped EditContext provided just above both, rather than two components wired together by a growing prop list.

Verified against

Claude Code Sonnet 4.6 · 2026-07-21

Cursor Cursor 2.1 · 2026-07-30

Changelog

  • 2026-07-21 Initial publish, verified against Claude Code (Sonnet 4.6) and Cursor 2.1.

Need this built into your business?

If a prompt isn't enough — custom software, built and maintained for you — that's Scult's day job.

EXPLORE CUSTOM SOFTWARE
All React prompts

Check your AI visibility

One URL in, a 0–100 score and the exact fixes out.

RUN THE CHECK

Browse all the tools

15 tools across six categories
13 of them never send your data anywhere

Free · No signup · No trial clock

SEE THE DIRECTORY