React Without Chaos: A Structure for Thinking Through Your Code
If you've ever found yourself re-reading a React component with more than 300 lines, trying to find where that mutation was, or why a useEffect fires when it shouldn't... then this guide is for you.
After years working on real products, collaborating with other devs, and maintaining legacy code, I arrived at a simple but powerful convention: a modular, organized, and scannable architecture for writing React components.
Why a structure?
In teams, consistency is key. But even when you're working alone, having a clear structure:
- Reduces reading time
- Makes debugging easier
- Helps detect errors faster
- Accelerates development of new features
Also, if you use react-query, next/router, multiple states, contexts, or custom hooks, chaos can appear quickly.
The structure: twelve blocks
I propose separating the component's logic into 12 clearly identifiable blocks, before the return, using comments as visual delimiters:
// QueryClient
// Router
// Context
// Constants
// Refs
// States
// Effects
// Hooks
// Queries
// Mutations
// Functions
// Computed
Why in this order? Start with the most global (queryClient, router, context), then declaration (constants, refs, states), then the reactive parts (effects, hooks), followed by communication (queries, mutations), and close with internal logic (functions) and derived variables (computed).
Simplified real example
export default function MyComponent() {
// QueryClient
const queryClient = useQueryClient();
// Router
const router = useRouter();
// Context
const { user } = useContext(UserContext);
// Constants
const ITEMS_PER_PAGE = 10;
// States
const [isOpen, setIsOpen] = useState(false);
// Effects
useEffect(() => {
if (!isOpen) console.log("Modal closed");
}, [isOpen]);
// Queries
const { data, isLoading } = useQuery(...);
// Mutations
const updateItem = useMutation(...);
// Functions
const handleSubmit = () => {
updateItem.mutate();
};
// Computed
const isPending = updateItem.isPending;
return <div>{isPending ? "Saving..." : "Ready"}</div>;
}
What I like most
Scannability: you know that if there's a mutation, it'll be in its place.
Maintainability: any developer can enter the component and get oriented in seconds.
Product mindset: you focus more on business logic, less on finding "where each thing is."
In projects that scale, order isn't a whim: ordering the code is ordering the mind.