• בלוג
  • ללמוד לקבל מגבלות

ללמוד לקבל מגבלות

28/07/2022

נניח שהגעתם לפרויקט ריאקט ויש בו עץ קומפוננטות מורכב שנגמר באיזה input, משהו כזה רק דמיינו שכל קומפוננטה יושבת בקובץ אחר והרבה יותר מורכבת:

function A(props) {
    return <B />
}

function B(props) {
    return <C />
}

function C(props) {
    return <D />
}

function D(props) {
    return <input type="text" />
}

ועכשיו אני רוצה להוסיף checkbox בקומפוננטה A שיגרום לתיבת הטקסט ב D להיות disabled. בואו נעשה את זה עוד יותר מעניין ונדמיין ש C ו D בכלל נכתבו בפרויקט אחר ויש עוד כמה עשרות פרויקטים שמשתמשים בהם.

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

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

אבל בעצם אני יודע ריאקט. ואני יכול לרמות. אני יכול לכתוב קוד ב A שיצלול פנימה ל D וישנה את מצב ה disabled של התיבה. בשבילכם אפילו כתבתי את זה:

import "./styles.css";
import { useState, useEffect, useRef } from "react";

export default function App() {
  const [disabled, setDisabled] = useState(false);
  const el = useRef(null);

  function handleChange(e) {
    if (e.target.checked) {
      setDisabled(true);
    } else {
      setDisabled(false);
    }
  }

  useEffect(() => {
    const checkbox = el.current.querySelector('input[type="text"]');
    checkbox.disabled = disabled;
  }, [disabled]);

  return (
    <div className="App" ref={el}>
      <h1>Hello CodeSandbox</h1>
      <label>
        <input type="checkbox" checked={disabled} onChange={handleChange} />
        Disabled
      </label>
      <A />
    </div>
  );
}

function A(props) {
  return <B />;
}

function B(props) {
  return <C />;
}

function C(props) {
  return <D />;
}

function D(props) {
  return <input type="text" />;
}

והנה אפילו סנדבוקס עם הקוד עובד: https://codesandbox.io/s/throbbing-snowflake-u6gv87?file=/src/App.js

מה שמחזיר אותנו לכותרת.

העלות הכי גבוהה בפיתוח היא לא פיתוח הפיצ'רים אלא תחזוקה שלהם. ריפקטורינג לכל הקומפוננטות זה סיפור יקר, אבל אחריו כולם זוכרים שקומפוננטות יכולות לעבוד גם במצב Disabled ולוקחים את זה בחשבון בכל פיתוח עתידי. כשאני עוקף את המגבלות בשביל להגיע למוצר עובד מהר יותר, אני רק מכניס מוקשים לקוד. כל שינוי עתידי קטן בקוד ישבור את הקוד שלי בלי שום אזהרה, ובלי שמי שמעדכן את D, C או B בכלל יודע שהוא שבר משהו.

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