Move one responsibility out of the large file
A bounded extraction is easier to understand than a simultaneous redesign.
When the project growsAbout 2 min read
The file size is a signal
An App.tsx can gradually collect navigation, requests, editing state and persistence rules. Each addition works locally, while a later change needs someone to understand more and more neighbouring behaviour. The difficulty is the number of connected responsibilities, not a universal line-count threshold.
Fiction Studio and My Next Step both use dedicated controllers for areas of behaviour. Those boundaries are useful when they make ownership clearer. Merely spreading the same entanglement across many small files can make investigation harder.
Define what crosses the boundary
Choose one coherent responsibility, such as opportunity matching or writing protection. List the inputs, returned state, callbacks and side effects that connect it to the rest of the application. Keep the owner of persisted data explicit.
For a React extraction, moving logic into a custom Hook shares that logic; it does not automatically create shared state between callers. Check state lifetime, effect cleanup, dependency changes and whether a rerender starts duplicate work. A controller is useful only if those behaviours remain understandable.
Keep one change easy to explain
Stabilise the intended behaviour enough to describe it, record focused checks, then move that responsibility without adding a new feature in the same change. Review both the extracted module and its remaining callers. An import moving successfully is not sufficient evidence.
Exercise the user journey afterward, including failure and return navigation. If extraction reveals a behaviour defect, record it separately or explicitly change the scope. Keeping that distinction makes it easier to tell whether the move preserved what mattered.