Component logic is simply how a component behaves — the decisions it makes, how it handles data, and how it interacts with user actions. Think of it as the brains of the component, separate from the UI/JSX.
What Counts as Component Logic
Everything inside the function but outside return is component logic:
- State (
useState) — stores values that the component tracks and reacts to. - Event handlers — functions like
toggleLogin,handleSubmit, oronChangethat respond to user actions and bridge the gap between what the user does and how the state updates. - Calculations and decisions — filtering or sorting data, conditional checks, derived values computed from state.
- Side effects (
useEffect) — fetching data from an API, setting up timers, subscribing to external sources.
import { useState } from "react";
function LoginStatus() {
// 👉 COMPONENT LOGIC STARTS HERE
const [isLoggedIn, setIsLoggedIn] = useState(false);
function toggleLogin() {
setIsLoggedIn(prev => !prev);
}
// 👉 COMPONENT LOGIC ENDS HERE
return (
<div>
<h2>{isLoggedIn ? "Welcome back!" : "Please log in"}</h2>
<button onClick={toggleLogin}>
{isLoggedIn ? "Logout" : "Login"}
</button>
</div>
);
}
export default LoginStatus;
In this example:
useState→ stores component state.toggleLogin→ an event handler that updates state in response to a button click.isLoggedIn ? ... : ...(used later in JSX) → decision-making logic.
What Is Not Component Logic
return ( ... )
The return block is JSX (markup). It describes structure and visual output — not behaviour. No state mutations or decisions are stored there.
Clean rule to remember:
- Component logic → state, handlers, calculations, decisions
- JSX → visual output
If you can move something out of return and the component still works, it's logic.
Component Logic Runs on Every Render
It is important to note that everything inside the function body — including logic — runs on every render. This means functions like toggleLogin are re-declared each time the component renders. For most components this is fine, but for performance-sensitive cases React provides hooks like useCallback and useMemo to control when logic is recalculated or recreated. These are covered in their own dedicated topics.
Why Keeping Logic and JSX Separate Matters
The distinction between component logic and JSX is not just conceptual — it has practical benefits:
- Maintainability — logic outside
returnis easier to read, scan, and modify without touching the visual structure. - Extractability — logic that lives outside
returncan be pulled into a custom hook and reused across multiple components. - Testability — pure logic functions (calculations, handlers) can be tested independently of the UI they power.
As your components grow in complexity, keeping logic and markup clearly separated is what prevents a component from becoming unmanageable.