React Hooks Changed How I Think About State
When React Hooks shipped I treated them as syntax sugar. Cleaner than class components, less boilerplate, same outcome. I rewrote a few components, liked the ergonomics, and moved on.
It took about a year of using them before I understood they were something more fundamental than that.
The class component mental model
In a class component, the unit of organisation is the lifecycle. You put data fetching in componentDidMount. You put cleanup in componentWillUnmount. You put derived state calculation in componentDidUpdate.
The logic for a single feature — say, a data table that fetches from an API, handles loading states, and refreshes when a filter changes — gets split across three or four lifecycle methods. The component file is organised around React's stages, not your feature.
This works. It scales badly. When a component has six features, each split across three lifecycle methods, the cognitive overhead of following any single feature through the file becomes significant.
What hooks changed
Hooks let you organise code by concern instead of by lifecycle stage.
function useTableData(filters: Filters) {
const [data, setData] = useState<Row[]>([])
const [loading, setLoading] = useState(false)
useEffect(() => {
setLoading(true)
fetchData(filters).then(rows => {
setData(rows)
setLoading(false)
})
}, [filters])
return { data, loading }
}
The fetch logic, the loading state, and the refetch trigger all live together in a custom hook. The component that uses it doesn't need to know any of that. It imports the hook, gets back what it needs.
The component file is now organised around what the component does for the user. The hooks are organised around what each piece of logic does for the component. Both layers are simpler separately than they were combined.
The composability consequence
Because hooks are just functions, they compose. useTableData can use useDebounce which uses useRef and useEffect. Each layer is simple; the composed behaviour is complex.
This is the same principle as function composition in general. Small, well-named functions that do one thing combine into larger behaviours without any single piece being difficult to understand.
I started thinking about state management differently as a result. Not "how do I manage state for this component" but "what is the shape of this concern, and what does a hook for it look like?"
What this changed about how I review code
Before hooks, a long component file was common and somewhat acceptable. There were only so many ways to organise class component code.
After hooks, a long component file is a smell. If a component's render function is doing significant computation, or if it's managing multiple distinct concerns, those concerns should be hooks. The component should read cleanly — mostly JSX, with a handful of hook calls at the top giving it what it needs.
If I'm reviewing a component and I can't understand what it does from its top-level structure in under a minute, the hooks haven't been extracted properly.
The thing no one mentioned
The shift from class components to hooks was positioned as an API change. It was actually a change in how you decompose problems.
Classes organised code around React's internals. Hooks let you organise code around your domain. That's a larger change than the syntax suggests — and it still shapes how I think about every component I write.