• בלוג
  • ריאקט מול ויו - שימו לב לשינויי סטייט

ריאקט מול ויו - שימו לב לשינויי סטייט

31/12/2024

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

בריאקט הקומפוננטה הבאה מגדירה שני ערכים ושני ערכים מחושבים:

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

export default function App() {
  const [x, setX] = useState(0);
  const [y, setY] = useState(0);
  const twoX = x * 2;
  const twoY = y * 2;

  return (
    <div className="App">
      <label>
        X:
        <input
          type="number"
          value={x}
          onChange={(e) => setX(Number(e.target.value))}
        />
        <span>x = {x}; </span>
        <span>2x = {twoX}</span>
      </label>
      <label>
        Y:
        <input
          type="number"
          value={y}
          onChange={(e) => setY(Number(e.target.value))}
        />
        <span>y = {y}; </span>
        <span>2y = {twoY}</span>
      </label>
    </div>
  );
}

אבל לא היינו כותבים קוד כזה בעולם האמיתי. הרזולוציה לא נכונה. בדוגמת הקוד גם כש x משתנה וגם כש y משתנה יש לחשב מחדש את שני הערכים המחושבים twoX ו twoY, בגלל שרזולוציית שינויים בריאקט היא קומפוננטה. בעולם האמיתי הקומפוננטה הזאת היתה מחולקת לשתי קומפוננטות, גם בגלל כפל הקוד וגם ובעיקר בגלל ה State - לקומפוננטה יש מספר אזורים שכל אחד מהם מושפע באופן עצמאי מסטייט אחר, וזה סימן ברור שמשהו בבחירת הקומפוננטה שלנו לא נכון.

ב Vue הסיפור קצת יותר מורכב אבל גם יותר קל למשתמשים. זאת הקומפוננטה:

<script setup>
import {ref, computed} from 'vue';
const x = ref(0);
const y = ref(0);
const twoX = computed(() => x.value * 2);
const twoY = computed(() => y.value * 2);
</script>

<template>
  <div class="App">
      <label>
        X:
        <input
          type="number"
          v-model="x"
        />
        <span>x = {{x}}; </span>
        <span>2x = {{twoX}}</span>
      </label>
      <label>
        Y:
        <input
          type="number"
          v-model="y"

        />
        <span>y = {{y}}; </span>
        <span>2y = {{twoY}}</span>
      </label>
    </div>
</template>

הקוד זהה אבל ההתנהגות שונה - שינוי ב x גורם לחישוב מחדש רק של twoX ושינוי ב y גורם לחישוב מחדש רק של twoY, כלומר רזולוציית השינוי היא לפי המשתנה והערכים שמחושבים ממנו. זה אומר שב vue יהיו לנו פחות בעיות ביצועים כתוצאה משינוי שיצא משליטה, אבל מצד שני יותר קשה לנו להבין את ההשפעה האמיתית של כל שינוי כי בשביל לראות מה מושפע מ x צריך לעקוב אחרי ה computed ולהסתכל על ה render function שנוצרה ואיזה חלקים ממנה מושפעים מכל ref.

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