میلی‌ثانیه‌ها می‌توانند تجربه‌های کاربری را ایجاد یا از بین ببرند، زیرا ناامیدی ناشی از تاخیر می‌تواند کاربران را از سایت ما دور کند. الگوی 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);

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 استفاده کنیم:

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

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

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

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

جمع‌بندی

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