برنامه نویسی

useMemo در مقابل useCallback – انجمن DEV 👩‍💻👨‍💻

useMemo و useCallback دو مورد از قلاب‌های واکنشی هستند که به ما در بهینه‌سازی عملکرد برنامه‌مان در زمان رندر شدن مجدد مؤلفه‌ها کمک می‌کنند. آنها می توانند بسیار مفید باشند در صورتی که بخواهید از انجام برخی محاسبات گران قیمت در برنامه خود جلوگیری کنید (مثلاً یک فراخوانی api به سروری که محاسبات گران قیمت را انجام می دهد).

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

از یادداشت استفاده کنید

قلاب useMemo برای برگرداندن یک مقدار ذخیره شده استفاده می شود. یادداشت کردن یک مفهوم رایج است که به برگرداندن یا استفاده مجدد از یک مقدار ذخیره شده به جای محاسبه آن در هر بار با توجه به عدم تغییر پارامترهای مورد استفاده برای محاسبه مقدار نسبت به محاسبه قبلی اشاره دارد.

نحو رسمی useMemo useMemo (expensiveFunction، [dependencies]). از نحو می توانیم ببینیم که useMemo دو آرگومان می گیرد. اولین آرگومان فراخوانی تابع گران قیمتی است که می خواهیم در حین رندر مجدد کامپوننت خود از آن اجتناب کنیم. این تابع باید خالص باشد، نمی تواند هیچ آرگومانی بگیرد و نتیجه این تابع می تواند از هر نوع باشد. آرگومان دوم فهرستی از وابستگی ها است.

تابعی که به useMemo ارسال می شود در اولین بار رندر کامپوننت ما فراخوانی می شود. اجرای مجدد بعدی به لیست وابستگی هایی بستگی دارد که به قلاب useMemo منتقل شده اند. اگر وابستگی ها تغییر نکرده باشند، مقدار قدیمی مجددا استفاده می شود در غیر این صورت مقدار جدید محاسبه می شود. اگر هیچ وابستگی ارسال نشود، تابع گران قیمت در هر رندر فراخوانی می شود.

مثال

import { useMemo } from 'react';

function UserList({ users, profile }) {
  const activeUsers = useMemo(() => filterActiveUsers(users, profile), [users]);
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال بالا، ما کاربرانی را به عنوان یک پایه در داخل کامپوننت خود دریافت کرده ایم. اجازه دهید بگوییم که filterActiveUsers فراخوانی روش بسیار گرانی است که زمان زیادی طول می کشد تا به نتیجه برسد. اگر بخواهیم هر بار که مؤلفه UserList ما اجرا می‌شود، روش گران قیمت را متوقف کنیم، می‌توانیم از useMemo برای متوقف کردن اجرای این تابع در دفعه بعد با توجه به اینکه وابستگی‌ها (کاربران و نمایه در این مورد) تغییر نمی‌کنند استفاده کنیم.

استفاده از برگشت تماس

useCallback برای بازگرداندن یک نسخه حفظ شده از یک تماس برگشتی استفاده می شود. مورد استفاده معمولی زمانی است که یک مؤلفه فرزند از مؤلفه والد انتظار پاسخ به تماس را دارد و ما می خواهیم از ارائه مجدد غیرضروری مؤلفه فرزند جلوگیری کنیم.

سینتکس useCallback useCallback است (تابع، [dependencies]). همانطور که می بینیم، بسیار شبیه useMemo است زیرا هم تابعی را به عنوان آرگومان اول می گیرند و هم لیستی از وابستگی ها را به عنوان آرگومان دوم می گیرند. تعریف تابعی که به‌عنوان پارامتر اول وارد می‌کنیم، حافظه پنهان است و همچنین می‌تواند برخی از آرگومان‌هایی را که می‌تواند برای منطق کسب‌وکار ما استفاده شود، در خود جای دهد.

React تابعی را که به عنوان آرگومان به قلاب useCallback در اولین رندر ارسال می شود، برمی گرداند (نه فراخوانی). دفعه بعد که این مؤلفه دوباره رندر می‌شود، react فهرست وابستگی را بررسی می‌کند و تنها در صورتی تعریف را محاسبه می‌کند که فهرست وابستگی‌ها از آخرین رندر تغییر کرده باشد.

مثال

import { useCallback } from 'react';

export default function Cart({ productId, userId, orderDetails }) {
  const handleSubmit = useCallback((orderDetails) => {
    post('/product/' + productId + '/buy', {
      userId,
      orderDetails,
    });
  }, [productId, userId, orderDetails]);

return (
    <div>
      <Shipping onSubmit={handleSubmit} />
    </div>
  );

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال بالا، useCallback تابعی را برمی گرداند که می تواند orderDetails را به عنوان آرگومان دریافت کند. تعریف تابع در handleSubmit ذخیره می شود. این تابع به نوبه خود می تواند به مؤلفه فرزند (حمل و نقل) منتقل شود. سپس مؤلفه فرزند می تواند از این تابع استفاده کند. تعریف تابع در حافظه پنهان ذخیره می شود و تنها در صورتی که وابستگی ها در رندرهای مجدد بعدی تغییر کنند دوباره محاسبه می شود.

مراقب باش! در استفاده از این روش ها زیاده روی نکنید!

در حالی که این دو قلاب راه حلی برای یک مشکل واقعی ارائه می دهند، اما باید مراقب باشیم که از آنها در مکان نامناسب استفاده نکنیم یا بیش از حد از آنها استفاده نکنیم.

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

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

تفاوت های کلیدی بین useMemo و useCallback

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

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا