רינדור מותנה

ב-React, אתם יכולים ליצור קומפוננטות יחודיות אשר מכמסות את ההתנהגות שאתם מחפשים. לאחר מכן, אתם יכולים לרנדר רק חלק מהן, על פי תלות ב-state של האפליקציה שלכם.

רינדור מותנה ב-React פועל באותו אופן שבו עובדים תנאים ב-JavaScript. השתמשו באופרטורים של JavaScript כמו if או האופרטו המותנה כדי ליצור אלמנטים המייצגים את ה-state הנוכחי, ותנו ל-React לעדכן את ממשק המשתמש כדי שיהיה תואם אליהם.

הביטו בשתי הקומפוננטות האלו:

function UserGreeting(props) {
  return <h1>ברוך הבא!</h1>;
}

function GuestGreeting(props) {
  return <h1>אנא הירשם.</h1>;
}

ניצור קומפוננטת Greeting שמציגה אחת מהקומפוננטות האלו כתלות באם משתמש מחובר:

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

ReactDOM.render(
  // Try changing to isLoggedIn={true}:
  <Greeting isLoggedIn={false} />,
  document.getElementById('root')
);

נסו זאת ב-CodePen

דוגמא זו מרנדרת ברכה שונה כתלות בערך של ה-prop isLoggedIn.

משתני אלמנט

אתם יכולים להשתמש במשתנים כדי לשמור אלמנטים. זה יכול לעזור לכם לרנדר חלק מהקומפוננטה באופן מותנה בעוד ששאר הפלט אינו משתנה.

הביטו בשתי הקומפוננטות החדשות המייצגות כפתורי התנתקות והתחברות:

function LoginButton(props) {
  return (
    <button onClick={props.onClick}>
      התחבר
    </button>
  );
}

function LogoutButton(props) {
  return (
    <button onClick={props.onClick}>
      התנתק
    </button>
  );
}

בדוגמה הבאה, ניצור קומפוננטה התלויה ב-state שנקראת LoginControl.

היא תרנדר <LoginButton /> או <LogoutButton /> כתלות ב-state הנוכחי שלה. בנוסף היא תרנדר <Greeting /> מהדוגמה הקודמת:

class LoginControl extends React.Component {
  constructor(props) {
    super(props);
    this.handleLoginClick = this.handleLoginClick.bind(this);
    this.handleLogoutClick = this.handleLogoutClick.bind(this);
    this.state = {isLoggedIn: false};
  }

  handleLoginClick() {
    this.setState({isLoggedIn: true});
  }

  handleLogoutClick() {
    this.setState({isLoggedIn: false});
  }

  render() {
    const isLoggedIn = this.state.isLoggedIn;
    let button;

    if (isLoggedIn) {
      button = <LogoutButton onClick={this.handleLogoutClick} />;
    } else {
      button = <LoginButton onClick={this.handleLoginClick} />;
    }

    return (
      <div>
        <Greeting isLoggedIn={isLoggedIn} />
        {button}
      </div>
    );
  }
}

ReactDOM.render(
  <LoginControl />,
  document.getElementById('root')
);

נסו זאת ב-CodePen

בעוד שהכרזה על משתנה ושימוש בהצהרה if היא דרך מצוינת להתנות רינדור קומפוננטה, לפעמים ייתכן שתרצו להשתמש בתחביר קצר יותר. ישנן מספר דרכים להטמיע תנאים ב-JSX, שמוסברות בהמשך.

הטמעת תנאי If עם אופרטור && לוגי

ייתכן שתרצו להטמיע כל ביטוי ב-JSX על ידי עטיפתם בסוגריים מסולסלים. זה כולל את האופרטור הלוגי && של JavaScript. זה יכול להיות שימושי עבור הוספה מותנית של אלמנט:

function Mailbox(props) {
  const unreadMessages = props.unreadMessages;
  return (
    <div>
      <h1>Hello!</h1>
      {unreadMessages.length > 0 &&
        <h2>
          יש לך {unreadMessages.length} הודעות שלא נקראו.
        </h2>
      }
    </div>
  );
}

const messages = ['React', 'Re: React', 'Re:Re: React'];
ReactDOM.render(
  <Mailbox unreadMessages={messages} />,
  document.getElementById('root')
);

נסו זאת ב-CodePen

זה עובד בגלל שב-JavaScript, true && expression תמיד שווה ערך ל-expression, ו-false && expression תמיד שווה ערך ל-false.

לכן, אם התנאי הוא true, האלמנט מימין אחרי && יופיע בפלט. אם הוא false, React תתעלם ממנו ותדלג עליו.

הטמעת If-Else עם אופרטור ההתנייה

שיטה נוספת להטמעת רינדור אלמנטים מותנה היא להשתמש באופרטור ההתנייה של JavaScript condition ? true : false.

בדוגמה הבאה, אנו משתמשים בו כדי לרנדר באופן מותנה בלוק קטן של טקסט.

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      המשתמש <b>{isLoggedIn ? 'כרגע' : 'לא'}</b> מחובר.
    </div>
  );
}

זה יכול לשמש גם עבור ביטויים גדולים יותר למרות שכך פחות ברור מה קורה:

render() {
  const isLoggedIn = this.state.isLoggedIn;
  return (
    <div>
      {isLoggedIn ? (
        <LogoutButton onClick={this.handleLogoutClick} />
      ) : (
        <LoginButton onClick={this.handleLoginClick} />
      )}
    </div>
  );
}

בדיוק כמו ב-JavaScript, זה באחריותכם לבחור סגנון מתאים על סמך מה שאתם והצוות שלכם מחשיבים יותר קריא. כמו כן זכרו שבכל פעם שתנאים נהיים מורכבים מדי, זה יכול להיות זמן טוב לחלץ קומפוננטה.

מניעת רינדור של קומפוננטה

במקרים נדירים ייתכן שתרצו שקומפוננטה תסתיר את עצמה למרות שהיא רונדרה על ידי קומפוננטה אחרת. כדי לעשות זאת החזירו null במקום את הפלט שאותו היא אמורה לרנדר.

בדוגמה הבאה, ה-<WarningBanner /> מרונדר בהתאם לערך של ה-prop שנקרא warn. אם ערך ה-prop הוא false, אזי הרכיב אינו מתרנדר:

function WarningBanner(props) {
  if (!props.warn) {
    return null;
  }

  return (
    <div className="warning">
      אזהרה!
    </div>
  );
}

class Page extends React.Component {
  constructor(props) {
    super(props);
    this.state = {showWarning: true};
    this.handleToggleClick = this.handleToggleClick.bind(this);
  }

  handleToggleClick() {
    this.setState(state => ({
      showWarning: !state.showWarning
    }));
  }

  render() {
    return (
      <div>
        <WarningBanner warn={this.state.showWarning} />
        <button onClick={this.handleToggleClick}>
          {this.state.showWarning ? 'הסתר' : 'הצג'}
        </button>
      </div>
    );
  }
}

ReactDOM.render(
  <Page />,
  document.getElementById('root')
);

נסו זאת ב-CodePen

החזרת null ממתודת render של קומפוננטה לא משפיעה על הרצת מתודות מחזור החיים של קומפוננטה. למשל componentDidUpdate עדיין יקרא.