مقدمه

تاکنون فرم‌هایی ساخته‌ایم که داده‌ها را در state کامپوننت مدیریت می‌کنند. اما در دنیای واقعی، هدف نهایی یک فرم معمولاً ارسال داده‌های آن به یک سرور برای پردازش یا ذخیره‌سازی است. در این درس، ما یاد می‌گیریم که چگونه پس از اعتبارسنجی موفق، داده‌های فرم را با استفاده از Fetch API به یک سرور خارجی ارسال کنیم.

مدیریت وضعیت ارسال (Submission State)

ارسال داده به یک سرور یک عملیات ناهمزمان (asynchronous) است و می‌تواند در وضعیت‌های مختلفی قرار گیرد: در حال ارسال (pending)، موفق (success)، یا ناموفق (error). ما باید UI خود را طوری طراحی کنیم که این وضعیت‌ها را به کاربر نمایش دهد. برای این کار، می‌توانیم از یک متغیر state جدید استفاده کنیم.

Copy Icon JAVASCRIPT (React)
import { useState } from 'react';

function ContactForm() {
  const [formData, setFormData] = useState({ name: '', email: '' });
  const [status, setStatus] = useState('typing'); // 'typing', 'submitting', 'success', 'error'
  
  async function handleSubmit(event) {
    event.preventDefault();
    setStatus('submitting');
    try {
      await submitForm(formData);
      setStatus('success');
    } catch (err) {
      setStatus('error');
      console.error(err);
    }
  }

  if (status === 'success') {
    return <h1>Thanks for your submission!</h1>;
  }

  // ... handleChange and JSX for the form ...
}

// Helper function that simulates a network request
function submitForm(data) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      // Simulate a 50% chance of success/failure
      if (Math.random() > 0.5) {
        resolve();
      } else {
        reject(new Error('Network error!'));
      }
    }, 1500);
  });
}

در این کد، ما یک state جدید به نام status با مقدار اولیه typing اضافه کرده‌ایم. در handler مربوط به ارسال فرم، ما ابتدا status را به submitting تغییر می‌دهیم. سپس، در یک بلوک try...catch تابع ناهمزمان submitForm را (که در اینجا یک درخواست شبکه را شبیه‌سازی می‌کند) فراخوانی می‌کنیم.

اگر Promise با موفقیت resolve شود، status را به success تغییر می‌دهیم. اگر reject شود، به بلوک catch رفته و status را به error تغییر می‌دهیم.

به‌روزرسانی UI بر اساس وضعیت ارسال

اکنون می‌توانیم با استفاده از state مربوط به status، UI خود را به صورت پویا تغییر دهیم تا به کاربر بازخورد مناسبی نمایش دهد.

Copy Icon
<form onSubmit={handleSubmit}>
  <!-- Input fields -->
  
  <button disabled={status === 'submitting'}>
    Submit
  </button>
  
  {status === 'submitting' && <p>Loading...</p>}
  {status === 'error' && <p style={{ color: 'red' }}>Something went wrong. Please try again.</p>}
</form>

در این JSX، ما از رندر شرطی برای نمایش بازخورد به کاربر استفاده کرده‌ایم:

  • غیرفعال کردن دکمه: اتریبیوت disabled دکمه به وضعیت submitting وابسته است. این کار از ارسال‌های مکرر فرم توسط کاربر جلوگیری می‌کند.
  • نمایش پیام "Loading...": زمانی که status برابر با submitting است، یک پیام بارگذاری نمایش داده می‌شود.
  • نمایش پیام خطا: در صورت بروز خطا، یک پیام خطای مناسب به کاربر نمایش داده می‌شود.

این الگو یک تجربه کاربری بسیار بهتر و قابل فهم‌تر ایجاد می‌کند، زیرا کاربر در هر مرحله از فرآیند ارسال فرم، بازخورد واضحی دریافت می‌کند.

در این درس، با مدیریت وضعیت‌های مختلف یک درخواست ناهمزمان، فرآیند ارسال فرم را تکمیل کردیم. دیدیم که چگونه می‌توان با استفاده از یک متغیر state برای ردیابی وضعیت، UI را به صورت پویا تغییر داد و بازخورد مناسبی به کاربر ارائه کرد.

با این درس، فصل «کار با فرم‌ها در ری‌اکت» به پایان می‌رسد. شما اکنون می‌توانید فرم‌های پیچیده، کنترل‌شده، با اعتبارسنجی و قابلیت تعامل با سرور بسازید. در فصل بعدی، به «هوک‌های پیشرفته برای مقیاس‌پذیری» خواهیم پرداخت و با ابزارهایی مانند useReducer و useContext برای مدیریت state در اپلیکیشن‌های بزرگ آشنا خواهیم شد.