React apps constantly need to show different UI based on conditions: a spinner while loading, an error message if something failed, a login button if the user isn’t authenticated. This is conditional rendering.You already know the JavaScript for this — ternary operators, &&, and if/else from the conditionals lesson. In React, you use the same patterns inside JSX.
&& is perfect when you want to either show something or show nothing. If the left side is truthy, the right side renders. If falsy, nothing renders.
Watch out for 0 && <Component />. Because 0 is falsy, React renders the number 0 on the page instead of nothing. Use count > 0 && <Component /> instead of count && <Component />.
Use && when you have a show/hide situation. Use ternary when you have an either/or situation. Keep ternaries simple — if the logic gets complex, extract it to a variable or use early returns.
For loading, error, and empty states, use early returns at the top of your component:
Copy
function UserList() { const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(null); // ... useEffect to fetch data ... // Early returns — check each state if (loading) return <Spinner />; if (error) return <ErrorMessage message={error} />; if (users.length === 0) return <p>No users found.</p>; // Main render — only reached when we have data return ( <ul> {users.map(user => ( <li key={user.id}>{user.name}</li> ))} </ul> );}
This is the standard pattern for data-fetching components. Check states in order of priority: loading → error → empty → data.
For complex class logic, consider a utility like clsx or classnames: className={clsx("btn", isPrimary && "btn-primary", isLarge && "btn-lg")}. It’s cleaner than manual string concatenation.