بررسی هوک useOptimistic در React

میلی‌ثانیه‌ها می‌توانند تجربه‌های کاربری را ایجاد یا از بین ببرند، زیرا ناامیدی ناشی از تاخیر می‌تواند کاربران را از سایت ما دور کند. الگوی optimistic UI یکی از استراتژی‌هایی است که به دلیل توانایی بالا در ارائه تعاملات سریع و ریسپانسیو، مورد توجه بسیاری از توسعه‌دهندگان قرار گرفته است. این الگو به ما اجازه می‌دهد تا بلافاصله پس از انجام یک عمل توسط کاربر، بر اساس این فرض که عملیات پس‌زمینه موفقیت‌آمیز بوده است، یک UI را به‌روزرسانی نماییم. این روش سرعت برنامه را افزایش می‌دهد و با ارائه بازخورد فوری، تجربه کاربری را تا حد زیادی بهبود می‌بخشد.

در این مقاله قصد داریم تا هوک useOptimistic، که از هوک‌های جدید React است را با هم بررسی کنیم و یاد بگیریم که این هوک چگونه می‌تواند به ما اجازه دهد تا برای این که برنامه‌ای سریع‌تر و ریسپانسیوتر داشته باشیم، به‌روزرسانی‌های optimistic UI را پیاده‌سازی نماییم.

هوک useOptimistic در React چیست؟

هوک UseOptimistic یک ویژگی قدرتمند است که در React 19 معرفی شده است و در حال حاضر در نسخه Canary React موجود می‌باشد. این هوک به ما اجازه می‌دهد تا زمانی که یک اکشن asynchronous، مانند درخواست شبکه، در حال انجام است، state دیگری را به کاربران نشان دهیم. این امر به ویژه در مواردی که کاربران انتظار بازخورد فوری برای اقدامات خود دارند، مانند هنگام ارسال فرم‌ها یا کامنت‌گذاری در رسانه‌های اجتماعی، بسیار مهم است.

با پیاده‌سازی هوک useOptimistic، برنامه‌ها می‌توانند فوراً UIها را به‌روزرسانی کنند و تجربه‌ای یکپارچه و جذاب را برای کاربران فراهم نمایند. در ادامه اجزای هوک useOptimistic را در یک مثال تحلیل می‌کنیم:

const [optimisticComments, postComment] = useOptimistic(commentsFromServer, addComment);
  • optimisticComments: این مورد optimistic state است که با مقدار commentsFromServer مقداردهی شده است و لیست فعلی کامنت‌های یک پست را نشان می‌دهد که هرگونه اکشن کاربر را بلافاصله منعکس می‌کند.
  • postComment: این گزینه تابع dispatch است که برای اعمال mutation تعریف شده در addComment فراخوانی می‌کنیم. زمانی که کاربر کامنتی را اضافه می‌کند، این تابع optimisticComments را به صورت optimistic به‌روزرسانی می‌نماید.
  • commentsFromServer: این گزینه نیز سورس truth است و لیست تایید شده کامنت‌های دریافت شده از سرور را نشان می‌دهد. اگر این مقدار تغییر کند (به عنوان مثال، پس از دریافت داده‌های جدید از سرور)، optimisticComments نیز برای مطابقت به‌روزرسانی می‌شود و از ثبات اطمینان حاصل می‌کند.
  • addComment: این مورد هم منطق mutation را بیان می‌کند که در هنگام فراخوانی postComment بر روی optimisticComments اعمال می‌شود. addComment تعریف می‌کند که چگونه می‌توانیم یک کامنت جدید را به صورت optimistic به لیست اضافه نماییم.

React هوک useOptimistic را که برای این الگوی UI طراحی شده بود، معرفی کرد. به‌روزرسانی optimistic UI تضمین می‌کند که کاربران منتظر پاسخ‌های سرور نمی‌مانند. این موضوع برای حفظ یک تجربه کاربری روان بسیار مهم است. هنگامی که کاربر اکشنی را انجام می‌دهد، useOptimistic تغییر state را بلافاصله قبل از پاسخ سرور نشان می‌دهد.

هوک useOptimistic با فرض اولیه اینکه API با موفقیت پاسخ می‌دهد، حالت optimistic را مدیریت می‌کند. اگر API با موفقیت پاسخ دهد، state فرض شده باقی می‌ماند. اما اگر API به هر دلیلی خراب شود، state به حالت اولیه خود باز می‌گردد. این تعادل برای حفظ یکپارچگی داده‌ها در عین ارائه تجربه کاربری که سریع و ریسپانسیو باشد، بسیار مهم است.

بررسی یک مثال: کامنت گذاشتن برای یک پست

یک پلتفرم رسانه اجتماعی را تصور می‌کنیم که در آن کاربران می‌توانند پست‌های دیگران را مشاهده کنند. وقتی کاربری بر روی دکمه Send کلیک می‌کند، برنامه قبل از به‌روزرسانی UI منتظر پاسخ سرور می‌ماند. این تأخیر می‌تواند باعث شود برنامه احساس کُندی به کاربر منتقل کند.

با فرض اینکه سروری را با فایل‌های لازم راه‌اندازی کرده‌ایم، به اجرای فانکشنالیتی optimistic ادامه می‌دهیم:

import { useState } from 'react';
import { useOptimistic } from 'react';

function CommentButton({ postId }) {
  const [comments, setComments] = useOptimistic([]);
  const [newComment, setNewComment] = useState('');
  const [error, setError] = useState('');

  const handleCommentSubmit = async () => {
    setError(''); // Clear any previous errors
    const optimisticNewComment = { id: Date.now(), text: newComment, status: 'sending' };
    setComments([...comments, optimisticNewComment]);  // Optimistically update the comments list

    try {
      const response = await api.postComment(postId, newComment);
      const updatedComments = comments.map(comment =>
        comment.id === optimisticNewComment.id ? { ...comment, status: 'sent' } : comment
      );
      setComments(updatedComments); // Update comment status to 'sent'
    } catch (error) {
      const filteredComments = comments.filter(comment => comment.id !== optimisticNewComment.id);
      setComments(filteredComments);
      setError('Failed to post comment. Please try again.');
    }
  };

  return (
    <div>
      <input 
        type="text"
        value={newComment}
        onChange={(e) => setNewComment(e.target.value)}
        placeholder="Write a comment..."
      />
      <button onClick={handleCommentSubmit} disabled={!newComment.trim()}>
        Post Comment
      </button>
      {comments.map(comment => (
        <div key={comment.id}>
          {comment.text} {comment.status === 'sending' && <span>(Sending...)</span>}
        </div>
      ))}
      {error && <p style={{ color: 'red' }}>{error}</p>}
    </div>
  );
}

export default CommentButton;

در این قطعه کد، optimistic state را مقداردهی اولیه می‌کنیم. متغیر state optimisticComments لیست کامنت‌هایی را که شامل هر گونه به‌روزرسانی optimistic است (کامنت‌هایی که بلافاصله با اضافه کردن کاربر، قبل از تأیید سرور ظاهر می‌شوند) در خود نگه می‌دارد. به عنوان یک آرایه خالی [] شروع می‌شود.

postComment تابعی است که از آن برای به‌روزرسانی optimistic optimisticComments استفاده می‌کنیم. این تابع یک کامنت جدید می‌گیرد و آن را به لیست کامنت‌های موجود اضافه می‌کند. تابع mutation (comments, newComment) \=> [...comments, newComment] نحوه به‌روزرسانی لیست کامنت‌ها را هنگام اضافه شدن کامنت جدید مشخص کرده و یک آرایه جدید شامل تمام کامنت‌های موجود و کامنت جدید می‌سازد.

برای ارسال یک کامنت به صورت optimistic، ابتدا باید یک optimistic comment ایجاد کنیم. optimisticNewComment یک آبجکت برای کامنت جدید است که ID موقت، متن از قسمت ورودی و وضعیت sending را شامل می‌شود. این آبجکت نمایانگر کامنتی است که کاربر به تازگی آن را اضافه کرده است.

سپس، برای دستیابی به یک به‌روزرسانی optimistic، از postComment(optimisticNewComment) استفاده می‌کنیم که فهرست optimisticComments را به‌روزرسانی می‌کند تا بلافاصله کامنت جدید را درج نماید و به کاربر بازخورد فوری ارائه دهد که کامنت او اضافه شده است.

پس از آن، بلاک try سعی می‌کند کامنت جدید را با استفاده از api.postComment(postId, newComment) به سرور ارسال نماید. اگر سرور تأیید کند که کامنت اضافه شده است، وضعیت optimisticNewComment به sent به‌روزرسانی می‌شود. سپس لیست کامنت‌ها برای منعکس کردن این وضعیت جدید به‌روزرسانی می‌شود. اگر server call ناموفق باشد، بلاک catch کامنت optimistic را از optimisticComments حذف می‌کند و یک پیام خطا تنظیم می‌کند تا به کاربر اطلاع دهد که کامنت او نمی‌تواند ارسال شود.

مقایسه Optimistic UI و متدهای مرسوم موجود

با پیاده‌سازی الگوی optimistic UI، برنامه‌ها می‌توانند به محض تعامل کاربر با آن‌ها، با به‌روزرسانی رابط‌های کاربری، واکنش‌پذیری فوری را انجام دهند. این موضوع به ویژه در محیط‌های تعامل یکپارچه مانند رسانه‌های اجتماعی بسیار حیاتی می‌باشد.

به‌روزرسانی‌های رابط‌های کاربری به شکل سنتی به زمان پاسخ‌دهی سرور متکی است، کاربران را در معرض زمان‌های انتظار طولانی قرار می‌دهد و باعث می‌شود اپلیکیشن به کُندی کار کند. optimistic UI با به‌روزرسانی پیشگیرانه رابط‌ها، این تجربه را متحول می‌کند و نتایجی را که کاربران انتظار دارند بعد از هر عملی که در سایت انجام می‌دهند مشاهده کنند، به کاربران نشان می‌دهد؛ مانند دیدن یک کامنت در لحظه‌ای که کلیک می‌شود.

این روش کاربران را فعالانه درگیر نگه می‌دارد و تجربه کلی آن‌ها را با اطمینان از جریان تعاملی مداوم و یکپارچه، افزایش می‌دهد. استفاده از این استراتژی برای حفظ رضایت کاربر در پلتفرم‌های با تعامل بالا بسیار مهم است.

Optimistic UI در محیط‌های قابل اعتماد

optimistic UI در سناریوهایی که اکشن‌ها تقریباً همیشه موفقیت‌آمیز هستند، مانند ارسال پیام یا به‌روزرسانی‌های ترجیحی در یک برنامه، جزء انتخاب‌های برتر است. در این زمینه‌ها، خطاهای سرور به جای قاعده، استثنا هستند و حتی زمانی که رخ می‌دهند، معمولاً تجربه کلی کاربر را مختل نمی‌کند. این قابلیت اطمینان، optimistic UI را به عنوان یک استراتژی کلیدی برای برنامه‌های مدرن با هدف افزایش حفظ و رضایت کاربر معرفی می‌کند.

چه زمانی باید از optimistic UI استفاده کنیم:

  • پلتفرم‌های رسانه‌های اجتماعی: اطمینان از بازخورد فوری برای اقداماتی مانند ارسال کامنت‌ها، لایک کردن پست‌ها و به اشتراک‌گذاری محتوا
  • اپلیکیشن‌های Ecommerce: ارائه به‌روزرسانی‌های فوری هنگام افزودن موارد مورد نظر به سبد خرید، فهرست علاقه‌مندی‌ها و یا در فرآیند پرداخت
  • ابزارهای مشارکتی: افزایش همکاری real-time با نمایش فوری تغییرات (مانند ویرایش‌های مربوط به یک داکیومنت یا به‌روزرسانی‌های تسک‌ها)
  • اپلیکیشن‌های پیام‌رسان: اجازه به کاربران برای مشاهده پیام‌های خود در قسمت گفتگو، بلافاصله بعد از ارسال
  • سیستم‌های رزرو: به‌روزرسانی اسلات‌ها یا رزروهای موجود در زمان واقعی برای جلوگیری از درگیری و بهبود رضایت کاربر

چه زمانی بهتر است از optimistic UI استفاده نکنیم:

  • تراکنش‌های مالی مهم: در مواردی که دقت و تأیید بسیار مهم است، مانند نقل و انتقالات بانکی یا معاملات سهام
  • اپلیکیشن‌های پزشکی: هنگام برخورد با داده‌های بهداشتی حساس یا اقداماتی که نیاز به به‌روزرسانی تأیید شده دارند
  • سیستم‌هایی با تأخیر بالا و اتصالات غیرقابل اعتماد: در جایی که احتمال درگیری یا خطا به دلیل به‌روزرسانی‌های optimistic زیاد است
  • مدیریت اسناد حقوقی: جایی که اطمینان از صحت و قانونی بودن هر تغییری بسیار مهم می‌باشد

مدیریت خطاها با استفاده از هوک useOptimistic

در حالی که optimistic UI مزایای متعددی را ارائه می‌کند، اما چالش‌هایی را نیز به همراه دارد، به ویژه در مدیریت موارد غیرمنتظره مانند خطاهای سرور. هوک useOptimistic در React با فعال کردن smooth rollback به state قبلی رابط کاربری در صورت عدم موفقیت یک عملکرد، این مشکل را برطرف می‌کند.

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

جمع‌بندی

در این مقاله، نحوه استفاده از هوک useOptimistic در React را بررسی کردیم تا بتوانیم با استفاده از آن، اپلیکیشن‌های سریع‌تر و ریسپانسیوتری بسازیم. این هوک تعامل با برنامه‌ها را یکپارچه و سریع می‌کند و باعث بهبود تجربه کاربری می‌شود.

دیدگاه‌ها:

افزودن دیدگاه جدید