Controlled در برابر Uncontrolled Components

یکی از موقعیت‌هایی که سؤال «چه کسی مسئول نگهداری داده است؟» به‌طور مشخص مطرح می‌شود، کار با عناصر فرم مانند input است. React برای این موضوع دو رویکرد متفاوت دارد: Controlled و Uncontrolled. فهم تفاوت این دو، پیش‌نیاز فصل بعدی است که به‌طور کامل به فرم‌ها می‌پردازد؛ در این درس فقط با مفهوم پایه این دو رویکرد آشنا می‌شویم.

رفتار پیش‌فرض عناصر فرم در HTML

به‌طور معمول، عناصری مانند input در HTML، مقدار خودشان را به‌صورت داخلی و در حافظه مرورگر نگه می‌دارند. یعنی وقتی کاربر تایپ می‌کند، خود عنصر DOM مقدار جدید را ذخیره می‌کند، بدون اینکه لزوماً کد جاوااسکریپت ما از این تغییر باخبر شود.

Uncontrolled Component: مقدار در اختیار DOM

وقتی اجازه می‌دهیم مقدار یک input توسط خود DOM مدیریت شود و فقط در صورت نیاز (مثلاً هنگام Submit) آن مقدار را بخوانیم، به آن Uncontrolled Component می‌گویند. برای خواندن مقدار در این حالت، معمولاً از Ref استفاده می‌شود که در فصل مربوط به Refs با جزئیات آن آشنا خواهیم شد:

function SearchForm() {
  const inputRef = useRef(null);

  function handleSubmit() {
    console.log(inputRef.current.value);
  }

  return <input ref={inputRef} />;
}

در این حالت، React خودش مقدار input را دنبال نمی‌کند؛ فقط در لحظه‌ای که نیاز داریم، مقدار فعلی را از DOM می‌خوانیم.

Controlled Component: مقدار در اختیار State

در رویکرد Controlled، مقدار یک input به‌طور کامل توسط State خود React مدیریت می‌شود، نه توسط DOM. یعنی مقدار input همیشه برابر با مقداری است که در State ذخیره شده، و هر تغییری در input باید از طریق به‌روزرسانی همان State اعمال شود:

function SearchForm() {
  const [query, setQuery] = useState("");

  return (
    <input
      value={query}
      onChange={(e) => setQuery(e.target.value)}
    />
  );
}

در این کد، ویژگی value مقدار input را به State متصل می‌کند و onChange هر تغییری را به State منتقل می‌کند. به همین دلیل، در هر لحظه، React دقیقاً می‌داند مقدار فعلی input چیست، بدون نیاز به خواندن مستقیم از DOM.

چرا Controlled معمولاً ترجیح داده می‌شود

چون در رویکرد Controlled، مقدار فرم همیشه در State قابل دسترسی است، انجام کارهایی مانند اعتبارسنجی لحظه‌ای، غیرفعال کردن دکمه بر اساس مقدار فعلی، یا هماهنگ کردن چند فیلد فرم با هم بسیار ساده‌تر می‌شود. جزئیات بیشتر این موضوعات را در فصل چهارم، مخصوص فرم‌ها، بررسی خواهیم کرد.

Uncontrolled هم کاربرد دارد

با این حال، Uncontrolled Components در برخی موقعیت‌ها همچنان مناسب هستند؛ مثلاً وقتی فقط نیاز داریم یک مقدار ساده را در لحظه Submit بخوانیم و نیازی به واکنش لحظه‌ای به هر تغییر نداریم. در چنین مواردی، استفاده از Ref می‌تواند ساده‌تر از تعریف State اضافی باشد.

مثال قابل اجرا

یک input به‌صورت Controlled
برای دیدن پیش‌نمایش کامپوننت، روی Run بزنید.

جمع‌بندی

در Controlled Component، مقدار عنصر فرم توسط State خود React مدیریت می‌شود و همیشه در دسترس است. در Uncontrolled Component، مقدار در اختیار خود DOM است و فقط در صورت نیاز، معمولاً با Ref، خوانده می‌شود. در درس بعدی به موضوع Coupling و Separation of Concerns در طراحی کامپوننت‌ها می‌پردازیم.