React is easy to get started with and just as easy to make messy. The difference between code that is a pleasure to maintain and code that feels intimidating rarely comes down to advanced tricks—it comes down to a few simple habits. These React best practices are for people who already write components but want to stop repeating the same mistakes.

Small components, one responsibility
The best component is one that does one thing and does it well. When a component starts mixing data fetching, business logic, and a large amount of JSX, it becomes a tangled knot that is difficult to understand and test.
Some signs that it is time to break a component apart: you have to scroll a lot to read the entire component, it contains several pieces of state that are unrelated, or you hesitate when naming it because it does too many things. Splitting early is cheaper than untangling later.
Keep state as close as possible to where it is used
A common temptation is to move all state to the top level “for convenience.” Almost always, the opposite is true: the farther state is from the components that actually use it, the more components re-render unnecessarily, and the harder it becomes to follow the data flow.
Keep each piece of state in the component that needs it. Only lift state when two components actually need to share the same information—and even then, lift it only to the nearest common ancestor, not one level higher.
useEffect does not mean “run when rendering”
This is the misunderstanding that causes the most bugs for people who are learning React. useEffect exists to synchronize your component with something outside React: a network request, a DOM event, a timer, or a subscription. It is not a generic hook for “run this code on every render.”
If you are using an effect only to calculate a value from props or state, you probably do not need an effect at all—see the next section.
Derive, don’t duplicate
Storing in state information that can be calculated from something else is an invitation to synchronization bugs: sooner or later, the two copies will disagree. If you have a list of items and want the total, do not store the total in separate state—calculate it when rendering. Less state means fewer things to keep synchronized and fewer ways to make a mistake.
Keys in lists are not decoration

When you render a list, React uses the key to know which item is which from one render to the next. Use a stable ID from the data as the key.
Using the array index as a shortcut seems harmless and works—until the list is reordered, an item is inserted in the middle, or one is removed. Then React gets confused about what changed, and you see state end up on the wrong item. A stable ID solves this at no extra cost.
Self-explanatory props and names
Good code reads almost like prose. Name components and props according to their intent, not their appearance: isLoading says more than flag, and onConfirm says more than handleClick2.
Also be suspicious when a component accumulates many boolean props (isBig, isPrimary, isDisabled, isRound, ...). That is often a sign that it is trying to be several components at once—and that brings us back to the first rule: break it into smaller pieces.
None of these practices is sophisticated, and that is precisely the point. Small components, state in the right place, effects used only for synchronization, and derived data instead of duplicated data: put it all together and you have a codebase that can grow without becoming a minefield. React will thank you—and so will your future self.


