רינדור מותנה
מבוא
לעיתים קרובות נרצה להציג תוכן שונה בהתאם למצב - למשל הודעת טעינה בזמן שהנתונים נטענים, או תפריט אחר למשתמש מחובר. ב-React אין תחביר תנאי מיוחד: משתמשים ב-JavaScript רגיל בתוך ה-JSX. בשיעור זה נעבור על השיטות המקובלות ונראה מתי כל אחת מהן מתאימה.
שיטות לרינדור מותנה
1. אופרטור Ternary ( ? : )
function Greeting({ isLoggedIn }) {
return (
<div>
{isLoggedIn ? (
<h1>ברוך הבא בחזרה!</h1>
) : (
<h1>אנא התחבר</h1>
)}
</div>
);
}
2. אופרטור && (Logical AND)
מציג תוכן רק אם התנאי true:
function Notifications({ count }) {
return (
<div>
{count > 0 && (
<span className="badge">{count}</span>
)}
</div>
);
}
// אם count = 0, לא יוצג כלום
// אם count = 5, יוצג <span class="badge">5</span>
⚠️ זהירות למלכודת נפוצה: האופרטור
&&מחזיר את הצד השמאלי כשהוא "נפילה" (falsy). המספר0הוא falsy, אך React דווקא מציגה אותו על המסך. לכן בודקים תמיד תנאי מפורש (למשלcount > 0) ולא נשענים על הערך עצמו:// ❌ בעיה {count && <span>{count}</span>} // אם count=0, יוצג "0" // ✅ פתרון {count > 0 && <span>{count}</span>}
3. if/else רגיל
function StatusMessage({ status }) {
let message;
if (status === 'loading') {
message = <p>טוען...</p>;
} else if (status === 'error') {
message = <p className="error">שגיאה!</p>;
} else if (status === 'success') {
message = <p className="success">הצלחה!</p>;
} else {
message = <p>לא ידוע</p>;
}
return <div>{message}</div>;
}
4. switch/case
function Icon({ type }) {
switch (type) {
case 'success':
return <span>✅</span>;
case 'error':
return <span>❌</span>;
case 'warning':
return <span>⚠️</span>;
default:
return <span>ℹ️</span>;
}
}
5. אובייקט מיפוי
function StatusIcon({ status }) {
const icons = {
success: '✅',
error: '❌',
warning: '⚠️',
info: 'ℹ️'
};
return <span>{icons[status] || icons.info}</span>;
}
דוגמאות מעשיות
הצגת Loading
function UserList() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetchUsers().then(data => {
setUsers(data);
setLoading(false);
});
}, []);
if (loading) {
return <div className="spinner">טוען...</div>;
}
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
טיפול בשגיאות
function DataDisplay() {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch('/api/data')
.then(res => res.json())
.then(setData)
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <p>⏳ טוען...</p>;
if (error) return <p>❌ שגיאה: {error}</p>;
if (!data) return <p>📭 אין נתונים</p>;
return <pre>{JSON.stringify(data, null, 2)}</pre>;
}
מצב ריק
function TodoList({ todos }) {
if (todos.length === 0) {
return (
<div className="empty-state">
<p>🎉 אין משימות!</p>
<p>הוסף משימה חדשה להתחיל</p>
</div>
);
}
return (
<ul>
{todos.map(todo => (
<li key={todo.id}>{todo.text}</li>
))}
</ul>
);
}
הסתרת קומפוננטה
החזרת null
function Modal({ isOpen, children }) {
if (!isOpen) {
return null; // לא מרנדר כלום
}
return (
<div className="modal-overlay">
<div className="modal-content">
{children}
</div>
</div>
);
}
CSS Display
function Toggle() {
const [visible, setVisible] = useState(true);
return (
<div>
<button onClick={() => setVisible(v => !v)}>
{visible ? 'הסתר' : 'הצג'}
</button>
<div style={{ display: visible ? 'block' : 'none' }}>
תוכן שאפשר להסתיר
</div>
</div>
);
}
Classes דינמיים
function Button({ isActive, isDisabled, children }) {
// שיטה 1: Template literal
const className = `btn ${isActive ? 'active' : ''} ${isDisabled ? 'disabled' : ''}`;
// שיטה 2: Array + filter + join
const classNames = [
'btn',
isActive && 'active',
isDisabled && 'disabled'
].filter(Boolean).join(' ');
return (
<button className={classNames} disabled={isDisabled}>
{children}
</button>
);
}
סיכום
| שיטה | מתי להשתמש |
|---|---|
condition ? a : b |
שני מצבים אפשריים |
condition && element |
הצגה/הסתרה פשוטה |
if/else |
לוגיקה מורכבת |
switch |
מספר מצבים קבועים |
return null |
הסתרה מלאה |
בדקו את עצמכם
נסו לענות לבד לפני שאתם פותחים את התשובה.
-
מה הסכנה ב-
{items.length && <List />}?הצגת התשובה
תשובה א. 0 הוא ערך ש-React מציגה. כותבים items.length > 0 && ...
-
איך מסתירים קומפוננטה לגמרי?
הצגת התשובה
תשובה א. קומפוננטה שמחזירה null לא מרנדרת כלום.