React
React component design principles
A handful of principles that keep React components easy to change. None of them are rules, but ignoring all of them tends to produce components that are painful to touch six months later.
Keep components small and focused
A component should do one thing. If you struggle to name it, or its render function scrolls off the screen, it is probably two components.
Separate presentation from logic
Push data fetching and business rules up into hooks or container components, and keep leaf components dumb. A dumb component that only takes props is trivial to test and reuse.
function useUser(id: string) {
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
let active = true;
getUser(id).then((u) => active && setUser(u));
return () => { active = false; };
}, [id]);
return user;
}
function UserCard({ user }: { user: User }) {
return <div className='card'>{user.name}</div>;
}
Lift state only as high as it needs to go
Shared state belongs at the closest common ancestor, not at the top of the app. Global state for everything makes every change ripple.
Props are a contract
- Keep the prop list short. Many props is a smell that the component does too much.
- Prefer specific props over a giant config object.
- Use children for composition instead of passing render logic through props.
Derive, do not duplicate
If a value can be computed from existing state or props, compute it during render instead of storing it in another piece of state. Duplicated state drifts out of sync.
// Do not store this in state, just derive it
const completed = todos.filter((t) => t.done).length;
Keys must be stable
List keys should be stable identifiers, not array indexes. Index keys cause subtle bugs when the list reorders or items are inserted.
