React is not your application
·2 min read ·React · Frontend · Architecture
React is a rendering library. Its job is to take state and produce UI. That's it. The moment your business logic lives inside components, you've given a rendering library responsibilities it was never designed to have.
The Component That Does Too Much
function OrderList() {
const [orders, setOrders] = useState([]);
useEffect(() => {
fetch('/api/orders')
.then(r => r.json())
.then(data => {
const processed = data
.filter(o => o.status !== 'cancelled')
.sort((a, b) => new Date(b.date) - new Date(a.date))
.map(o => ({ ...o, total: calculateTotal(o.items) }));
setOrders(processed);
});
}, []);
// 80 more lines of rendering...
}
Business logic, data fetching, transformation, and rendering—all in one place. Good luck testing any of it.
Where Logic Should Actually Live
Custom hooks handle data fetching and local state. Service functions handle transformation and business rules. Components handle rendering.
// Component is now just rendering:
function OrderList() {
const { orders, loading } = useOrders();
if (loading) return <Spinner />;
return orders.map(order => <OrderCard key={order.id} order={order} />);
}
useOrders is a custom hook. The filtering and sorting logic lives in a pure processOrders() function you can test without a browser.
The Payoff
When your business logic is decoupled from React, you can unit test it without rendering anything, reuse it across components, and swap out React without rewriting your application logic.
React is not your application. It's your view layer. Treat it accordingly.