useMemo: چیست، کش‌کردن محاسبات و React Native

نویسنده: IT Sectr منتشر شده: 2026-07-05 زمان مطالعه: 10 دقیقه

هوک useMemo در React Native نتیجه محاسبات را بین رندرهای کامپوننت مموری‌سازی می‌کند و از اجرای مجدد عملیات‌های پرهزینه جلوگیری می‌نماید. برخلاف useCallback که تابع را مموری‌سازی می‌کند، useMemo مقدار بازگشتی را ذخیره کرده و آن را فقط هنگام تغییر وابستگی‌های مشخص‌شده مجدداً محاسبه می‌کند. طبق React Docs, 2024، مموری‌سازی به‌ویژه برای محاسبات با آرایه‌های بزرگ و تبدیل‌های پیچیده داده مؤثر است. در React Native هر رندر مجدد اضافی بار اضافی بر اتصال پل بین جاوااسکریپت و تردهای بومی ایجاد می‌کند، بنابراین استفاده صحیح از useMemo مستقیماً بر روانی انیمیشن‌ها و سرعت پاسخگویی رابط تأثیر می‌گذارد.

نکات کلیدی

  • useMemo — هوک React برای مموری‌سازی مقادیر که نتیجه تابع را بین رندرها کش می‌کند
  • هوک دو آرگومان می‌پذیرد: تابع محاسبه‌گر و آرایه وابستگی‌ها
  • مقدار فقط زمانی مجدداً محاسبه می‌شود که حداقل یک وابستگی تغییر کند
  • در React Native useMemo برای بهینه‌سازی عملکرد لیست‌ها و انیمیشن‌ها حیاتی است
  • استفاده بیش از حد از useMemo ممکن است به دلیل هزینه مقایسه وابستگی‌ها عملکرد را بدتر کند

useMemo در React Native چیست

useMemo — هوکی از کتابخانه استاندارد React است که در React Native بدون بسته‌های اضافی در دسترس می‌باشد. این هوک مقدار بازگشتی از تابع ارسال‌شده را مموری‌سازی کرده و این مقدار را در رندرهای بعدی تا زمانی که وابستگی‌های مشخص‌شده در آرایه تغییر نکنند، مجدداً استفاده می‌کند.

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

در زمینه React Native مموری‌سازی به دلیل معماری خاص آن اهمیت ویژه‌ای دارد. هر رندر مجدد کامپوننت داده‌ها را از طریق پل جاوااسکریپت — بومی ارسال می‌کند که زمان‌بر است. اگر کامپوننت شامل محاسبات پرهزینه (فیلتر کردن لیست، مرتب‌سازی، قالب‌بندی) باشد، هر رندر مجدد آنها را تکرار کرده، ترد JS را مسدود کرده و باعث افت فریم می‌شود.

طبق React Native Performance Docs, 2024، تنگنا اغلب نه رندر کامپوننت‌های بومی، بلکه اجرای منطق جاوااسکریپت بین رندرها است. useMemo دقیقاً همین مشکل را حل می‌کند.

مموری‌سازی مقادیر چگونه کار می‌کند

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

سینتکس و ارسال آرگومان‌ها

امضای useMemo در وب و React Native کاملاً یکسان است. آرگومان اول — تابع بدون پارامتر که مقدار مموری‌شونده را بازمی‌گرداند. دوم — آرایه وابستگی‌ها که با تغییر آنها مقدار مجدداً محاسبه خواهد شد.

js
import React, { useMemo } from 'react';

const sortedList = useMemo(() => {
    return items.sort((a, b) => a.name.localeCompare(b.name));
}, [items]);

در این مثال sortedList فقط زمانی مجدداً محاسبه می‌شود که رفرنس آرایه items تغییر کند. اگر آرایه از نظر محتوا تغییر کرده باشد اما رفرنس ثابت مانده باشد (جهش)، useMemo تغییر را نخواهد دید — این یک محدودیت مهم است.

مقایسه وابستگی‌ها با Object.is

React برای مقایسه وابستگی‌ها از الگوریتم Object.is استفاده می‌کند که مشابه برابری سخت‌گیرانه === عمل می‌کند اما NaN را به درستی مدیریت می‌کند (+0 و -0 متفاوت در نظر گرفته می‌شوند). این بدان معناست که برای انواع اولیه (رشته‌ها، اعداد، بولین‌ها) مقایسه بر اساس مقدار و برای اشیاء و آرایه‌ها بر اساس رفرنس انجام می‌شود.

js
// Object.is({'a': 1}, {'a': 1}) -> false (ارجاع‌های متفاوت)
// Object.is(42, 42) -> true (اولیه بر اساس مقدار)
// Object.is(NaN, NaN) -> true (مدیریت صحیح NaN)

درک این مکانیسم حیاتی است: اگر در هر رندر یک شیء جدید به وابستگی‌ها ارسال شود، مموری‌سازی بی‌فایده خواهد بود، زیرا وابستگی‌ها هر بار تغییر یافته تلقی می‌شوند.

چه زمانی از useMemo استفاده کنیم

useMemo در سه سناریو توجیه‌پذیر است: محاسبات پرهزینه، ارسال props پایدار به کامپوننت‌های فرزند و حفظ هویت رفرنسی اشیاء. در React Native هر سه سناریو به دلیل ویژگی‌های معماری برنامه‌های موبایل به طور منظم رخ می‌دهند.

محاسبات پرهزینه

اگر کامپوننت پردازش آرایه‌های داده بزرگ (فیلتر کردن، مرتب‌سازی، گروه‌بندی) یا عملیات ریاضی منابع‌بر را انجام می‌دهد، useMemo از تکرار این محاسبات در هر رندر مجدد جلوگیری می‌کند. در برنامه‌های موبایل مثال معمول — قالب‌بندی داده‌های API قبل از نمایش در لیست است.

props پایدار برای کامپوننت‌های فرزند

وقتی کامپوننت فرزند در React.memo پیچیده شده است، فقط با تغییر props مجدداً رندر می‌شود. اگر شیء props در داخل والد بدون useMemo ایجاد شود، در هر رندر والد یک رفرنس جدید ایجاد شده و کامپوننت فرزند دوباره رندر می‌شود و فایده React.memo را از بین می‌برد.

مموری‌سازی محاسبات استایل

در React Native استایل‌ها اغلب به props وابسته هستند — مثلاً عرض یک عنصر بر اساس اندازه صفحه محاسبه می‌شود. useMemo امکان محاسبه این استایل‌های پویا را فقط هنگام تغییر پارامترهای ورودی فراهم می‌کند.

چه زمانی useMemo بی‌فایده است

useMemo یک ابزار بهینه‌سازی جهانی نیست. در برخی سناریوها سودی ندارد و حتی ممکن است به دلیل سربار ذخیره‌سازی و مقایسه وابستگی‌ها عملکرد را بدتر کند. در React Native، جایی که هر بایت حافظه مهم است، استفاده کورکورانه از useMemo بدون اندازه‌گیری اثر، یک ضدالگو محسوب می‌شود.

هوک در سه مورد اصلی سودمند نیست. اول، اگر محاسبه ساده باشد (جمع ساده، الحاق رشته‌ها)، هزینه‌های useMemo از ارزش خود محاسبه فراتر می‌رود. دوم، اگر وابستگی‌ها هر رندر تغییر کنند — تابع همچنان اجرا خواهد شد و مموری‌سازی فقط کار اضافی ایجاد می‌کند. سوم، اگر کامپوننت به ندرت رندر می‌شود، سربار ذخیره‌سازی کش توجیه‌پذیر نیست.

طبق Kent C. Dodds, 2023، قبل از افزودن useMemo باید مشکل را با React DevTools Profiler یا Performance Monitor داخلی در React Native اندازه‌گیری کنید. اگر رندر مجدد کامپوننت کمتر از 1 میلی‌ثانیه طول بکشد، مموری‌سازی لازم نیست.

  • محاسبات ساده — جمع، الحاق، عملیات ternary ساده
  • رندرهای مجدد نادر — صفحات ایستا که یک بار رندر می‌شوند
  • وابستگی‌های متغیر — اگر وابستگی‌ها در هر رندر جدید باشند، مموری‌سازی بی‌فایده است
  • مقادیر اولیه — اعداد و رشته‌ها نیاز به مموری‌سازی ندارند، آنها به خودی خود ارزان هستند

useMemo و useCallback: مقایسه

useMemo و useCallback — دو هوک مموری‌سازی از React که اغلب اشتباه گرفته می‌شوند. تفاوت در این است که چه چیزی را ذخیره می‌کنند: useMemo نتیجه اجرای تابع (هر مقداری) را بازمی‌گرداند، در حالی که useCallback خود تابع را بازمی‌گرداند. هر دو آرایه وابستگی می‌پذیرند اما سینتکس متفاوت است.

ویژگیuseMemouseCallback
بازمی‌گرداندنتیجه اجرای تابعرفرنس به تابع
آرگومان اولتابعی که مقدار بازمی‌گرداندتابعی که باید مموری‌سازی شود
کاربرد معمولکش کردن محاسباتcallbackهای پایدار برای کامپوننت‌های فرزند
معادلuseMemo(() => fn, deps)useCallback(fn, deps) === useMemo(() => fn, deps)

در عمل useCallback — شکر نحوی بر روی useMemo برای مواردی است که نیاز به مموری‌سازی تابع داریم. در React Native هر دو هوک به یک اندازه استفاده می‌شوند: useMemo — برای داده‌ها (متن قالب‌بندی‌شده، استایل‌های محاسبه‌شده)، useCallback — برای handlerهای رویداد (onPress, onChangeText).

مثال‌های عملی با useMemo

دو سناریوی واقعی استفاده از useMemo در برنامه‌های React Native را بررسی می‌کنیم. اولی — فیلتر کردن لیست مخاطبین بر اساس عبارت جستجو، دومی — محاسبه استایل‌های پویا بر اساس اندازه صفحه.

مثال 1: جستجو و فیلتر کردن لیست

در این مثال useMemo از فیلتر کردن مجدد لیست بزرگ مخاطبین در هر رندر جلوگیری می‌کند، اگر نه عبارت جستجو و نه داده‌های منبع تغییر نکرده باشند.

js
const ContactList = ({ contacts, searchQuery }) => {
    const filteredContacts = useMemo(() => {
        if (!searchQuery.trim()) return contacts;
        const query = searchQuery.toLowerCase();
        return contacts.filter((c) =>
            c.name.toLowerCase().includes(query) ||
            c.phone.includes(query)
        );
    }, [contacts, searchQuery]);

    return (
        <FlatList
            data={filteredContacts}
            renderItem={renderContact}
            keyExtractor={(item) => item.id}
        />
    );
};

بدون useMemo فیلتر کردن در هر رندر اجرا می‌شد، از جمله رندرهای ناشی از انیمیشن‌ها یا تغییر وضعیت سایر بخش‌های کامپوننت. با useMemo فیلتر کردن فقط هنگام تغییر contacts یا searchQuery اجرا می‌شود.

مثال 2: محاسبه استایل‌های پویا

در React Native استایل‌ها اغلب به اندازه‌های صفحه یا props کامپوننت وابسته هستند. useMemo امکان محاسبه یکبار این شیء استایل و استفاده مجدد از آن را تا زمانی که وابستگی‌ها تغییر نکنند فراهم می‌کند.

js
const Card = ({ title, isSelected }) => {
    const cardStyle = useMemo(() => ({
        backgroundColor: isSelected ? '#e3f2fd' : '#ffffff',
        borderWidth: isSelected ? 2 : 1,
        padding: 16,
    }), [isSelected]);

    return (
        <View style={cardStyle}>
            <Text>{title}</Text>
        </View>
    );
};

این رویکرد تضمین می‌کند که شیء cardStyle تا زمانی که isSelected تغییر نکند پایدار (همان رفرنس) باقی می‌ماند. اگر Card در React.memo پیچیده شده باشد، این الگو از رندرهای مجدد غیرضروری عناصر فرزند جلوگیری می‌کند.

سوالات متداول

useMemo چه چیزی را بازمی‌گرداند؟

useMemo مقدار مموری‌شده را بازمی‌گرداند — نتیجه اجرای تابع ارسال‌شده به عنوان آرگومان اول. در رندرهای بعدی، React مقدار ذخیره‌شده را بازمی‌گرداند اگر وابستگی‌ها تغییر نکرده باشند.

تفاوت useMemo و useCallback چیست؟

useMemo نتیجه اجرای تابع را بازمی‌گرداند (هر مقداری: عدد، شیء، JSX)، در حالی که useCallback خود تابع را بازمی‌گرداند. همچنین useCallback(fn, deps) معادل useMemo(() => fn, deps) است.

چه زمانی useMemo لازم نیست؟

useMemo در محاسبات ساده (جمع، الحاق)، رندرهای مجدد نادر، وابستگی‌هایی که در هر رندر تغییر می‌کنند و برای انواع اولیه بی‌فایده است. همیشه قبل از افزودن useMemo عملکرد را اندازه‌گیری کنید.

آیا useMemo می‌تواند عملکرد را بدتر کند؟

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

چگونه عملکرد useMemo را دیباگ کنیم؟

از React DevTools Profiler برای اندازه‌گیری زمان رندر کامپوننت‌ها استفاده کنید. در React Native همچنین Performance Monitor از طریق منوی توسعه‌دهنده در دسترس است. اگر رندر مجدد کمتر از 1 میلی‌ثانیه طول بکشد — useMemo لازم نیست.

خلاصه

  • useMemo — هوک React برای مموری‌سازی مقادیر که نتیجه تابع را بین رندرها کش می‌کند
  • هوک تابع محاسبه‌گر و آرایه وابستگی‌ها را می‌پذیرد و مقدار را فقط هنگام تغییر آنها مجدداً محاسبه می‌کند
  • در React Native useMemo برای بهینه‌سازی لیست‌ها، انیمیشن‌ها و محاسبات پیچیده حیاتی است
  • سناریوهای کلیدی: محاسبات پرهزینه، props پایدار برای React.memo، استایل‌های پویا
  • useMemo با useCallback متفاوت است: اولی مقدار بازمی‌گرداند، دومی — تابع
  • استفاده بیش از حد از useMemo به دلیل سربار ذخیره‌سازی و مقایسه وابستگی‌ها عملکرد را بدتر می‌کند
  • قبل از افزودن useMemo همیشه مشکل را با React DevTools Profiler یا Performance Monitor در React Native اندازه‌گیری کنید

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید