فارسی

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

React Memo: بررسی عمیق تکنیک‌های بهینه‌سازی برای اپلیکیشن‌های جهانی

ری‌اکت یک کتابخانه قدرتمند جاوااسکریپت برای ساخت رابط‌های کاربری است، اما با افزایش پیچیدگی اپلیکیشن‌ها، بهینه‌سازی عملکرد اهمیت حیاتی پیدا می‌کند. یکی از ابزارهای ضروری در جعبه‌ابزار بهینه‌سازی ری‌اکت React.memo است. این پست وبلاگ یک راهنمای جامع برای درک و استفاده مؤثر از React.memo و تکنیک‌های مرتبط برای ساخت اپلیکیشن‌های ری‌اکت با کارایی بالا برای مخاطبان جهانی ارائه می‌دهد.

React.memo چیست؟

React.memo یک کامپوننت مرتبه بالا (HOC) است که یک کامپوننت تابعی را مموایز (memoize) می‌کند. به زبان ساده‌تر، از رندر مجدد یک کامپوننت در صورتی که props آن تغییر نکرده باشد، جلوگیری می‌کند. به طور پیش‌فرض، این کار را با مقایسه سطحی (shallow comparison) propsها انجام می‌دهد. این امر می‌تواند به طور قابل توجهی عملکرد را بهبود بخشد، به‌ویژه برای کامپوننت‌هایی که رندر آن‌ها از نظر محاسباتی سنگین است یا حتی زمانی که propsهایشان ثابت می‌ماند، به طور مکرر رندر می‌شوند.

کامپوننتی را تصور کنید که پروفایل یک کاربر را نمایش می‌دهد. اگر اطلاعات کاربر (مانند نام، آواتار) تغییر نکرده باشد، نیازی به رندر مجدد کامپوننت نیست. React.memo به شما اجازه می‌دهد از این رندر مجدد غیرضروری صرف‌نظر کنید و در زمان پردازش ارزشمند صرفه‌جویی کنید.

چرا از React.memo استفاده کنیم؟

در اینجا مزایای کلیدی استفاده از React.memo آمده است:

استفاده پایه از React.memo

استفاده از React.memo ساده است. کافی است کامپوننت تابعی خود را با آن بپوشانید:

import React from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
{props.data}
); }; export default React.memo(MyComponent);

در این مثال، MyComponent فقط در صورتی رندر مجدد می‌شود که prop با نام data تغییر کند. عبارت console.log به شما کمک می‌کند تا تأیید کنید که کامپوننت چه زمانی واقعاً رندر مجدد می‌شود.

درک مقایسه سطحی (Shallow Comparison)

به‌طور پیش‌فرض، React.memo یک مقایسه سطحی (shallow comparison) از propsها انجام می‌دهد. این به این معنی است که بررسی می‌کند آیا ارجاع (references) به propsها تغییر کرده است یا نه، نه خود مقادیر. درک این موضوع هنگام کار با اشیاء و آرایه‌ها مهم است.

مثال زیر را در نظر بگیرید:

import React, { useState } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
{props.data.name}
); }; const MemoizedComponent = React.memo(MyComponent); const App = () => { const [user, setUser] = useState({ name: 'John', age: 30 }); const handleClick = () => { setUser({ ...user }); // Creating a new object with the same values }; return (
); }; export default App;

در این حالت، حتی اگر مقادیر شیء user (یعنی name و age) ثابت باقی بمانند، تابع handleClick هر بار که فراخوانی می‌شود، یک ارجاع شیء جدید ایجاد می‌کند. بنابراین، React.memo تشخیص می‌دهد که prop با نام data تغییر کرده است (زیرا ارجاع شیء متفاوت است) و MyComponent را رندر مجدد می‌کند.

تابع مقایسه سفارشی

برای حل مشکل مقایسه سطحی با اشیاء و آرایه‌ها، React.memo به شما اجازه می‌دهد تا یک تابع مقایسه سفارشی را به عنوان آرگومان دوم آن ارائه دهید. این تابع دو آرگومان می‌گیرد: prevProps و nextProps. اگر کامپوننت نباید رندر مجدد شود (یعنی propsها عملاً یکسان هستند) باید true برگرداند و اگر باید رندر مجدد شود، false برگرداند.

در اینجا نحوه استفاده از یک تابع مقایسه سفارشی در مثال قبلی آمده است:

import React, { useState, memo } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
{props.data.name}
); }; const areEqual = (prevProps, nextProps) => { return prevProps.data.name === nextProps.data.name && prevProps.data.age === nextProps.data.age; }; const MemoizedComponent = memo(MyComponent, areEqual); const App = () => { const [user, setUser] = useState({ name: 'John', age: 30 }); const handleClick = () => { setUser({ ...user }); }; return (
); }; export default App;

در این مثال به‌روز شده، تابع areEqual ویژگی‌های name و age اشیاء user را مقایسه می‌کند. اکنون MemoizedComponent فقط در صورتی رندر مجدد می‌شود که name یا age تغییر کند.

چه زمانی از React.memo استفاده کنیم؟

React.memo در سناریوهای زیر بیشترین تأثیر را دارد:

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

جایگزین‌های React.memo

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

۱. PureComponent

برای کامپوننت‌های کلاسی، PureComponent عملکردی مشابه React.memo ارائه می‌دهد. این کامپوننت یک مقایسه سطحی از props و state انجام می‌دهد و تنها در صورت وجود تغییرات، رندر مجدد می‌کند.

import React from 'react';

class MyComponent extends React.PureComponent {
 render() {
 console.log('MyComponent rendered');
 return (
 
{this.props.data}
); } } export default MyComponent;

PureComponent یک جایگزین مناسب برای پیاده‌سازی دستی shouldComponentUpdate است که روش سنتی برای جلوگیری از رندرهای مجدد غیرضروری در کامپوننت‌های کلاسی بود.

۲. shouldComponentUpdate

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

import React from 'react';

class MyComponent extends React.Component {
 shouldComponentUpdate(nextProps, nextState) {
 return nextProps.data !== this.props.data;
 }

 render() {
 console.log('MyComponent rendered');
 return (
 
{this.props.data}
); } } export default MyComponent;

در حالی که shouldComponentUpdate هنوز در دسترس است، PureComponent و React.memo به طور کلی به دلیل سادگی و سهولت استفاده ترجیح داده می‌شوند.

۳. useCallback

useCallback یک هوک ری‌اکت است که یک تابع را مموایز می‌کند. این هوک یک نسخه مموایز شده از تابع را برمی‌گرداند که تنها در صورتی تغییر می‌کند که یکی از وابستگی‌های آن تغییر کرده باشد. این امر به ویژه برای ارسال callbackها به عنوان prop به کامپوننت‌های مموایز شده مفید است.

مثال زیر را در نظر بگیرید:

import React, { useState, useCallback, memo } from 'react';

const MyComponent = (props) => {
 console.log('MyComponent rendered');
 return (
 
 );
};

const MemoizedComponent = memo(MyComponent);

const App = () => {
 const [count, setCount] = useState(0);

 const handleClick = useCallback(() => {
 setCount(count + 1);
 }, [count]);

 return (
 

Count: {count}

); }; export default App;

در این مثال، useCallback تضمین می‌کند که تابع handleClick تنها زمانی تغییر می‌کند که state با نام count تغییر کند. بدون useCallback، یک تابع جدید در هر رندر App ایجاد می‌شد و باعث رندر مجدد غیرضروری MemoizedComponent می‌شد.

۴. useMemo

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

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

const App = () => {
 const [input, setInput] = useState('');

 const expensiveCalculation = (str) => {
 console.log('Calculating...');
 let result = 0;
 for (let i = 0; i < str.length * 1000000; i++) {
 result++;
 }
 return result;
 };

 const memoizedResult = useMemo(() => expensiveCalculation(input), [input]);

 return (
 
setInput(e.target.value)} />

Result: {memoizedResult}

); }; export default App;

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

مثال‌های عملی برای اپلیکیشن‌های جهانی

بیایید چند مثال عملی از نحوه استفاده از React.memo و تکنیک‌های مرتبط در اپلیکیشن‌های جهانی را بررسی کنیم:

۱. انتخاب‌گر زبان

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

import React, { memo } from 'react';

const LanguageItem = ({ language, onSelect }) => {
 console.log(`LanguageItem ${language} rendered`);
 return (
 
  • onSelect(language)}>{language}
  • ); }; const MemoizedLanguageItem = memo(LanguageItem); const LanguageSelector = ({ languages, onSelect }) => { return (
      {languages.map((language) => ( ))}
    ); }; export default LanguageSelector;

    در این مثال، MemoizedLanguageItem فقط در صورتی رندر مجدد می‌شود که prop با نام language یا onSelect تغییر کند. این امر به ویژه اگر لیست زبان طولانی باشد یا اگر کنترل‌کننده onSelect پیچیده باشد، می‌تواند مفید باشد.

    ۲. مبدل ارز

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

    import React, { memo } from 'react';
    
    const CurrencyItem = ({ currency, rate, onSelect }) => {
     console.log(`CurrencyItem ${currency} rendered`);
     return (
     
  • onSelect(currency)}>{currency} - {rate}
  • ); }; const MemoizedCurrencyItem = memo(CurrencyItem); const CurrencyConverter = ({ currencies, onSelect }) => { return (
      {Object.entries(currencies).map(([currency, rate]) => ( ))}
    ); }; export default CurrencyConverter;

    در این مثال، MemoizedCurrencyItem فقط در صورتی رندر مجدد می‌شود که prop با نام currency، rate یا onSelect تغییر کند. این می‌تواند عملکرد را بهبود بخشد اگر لیست ارزها طولانی باشد یا اگر به‌روزرسانی‌های نرخ تبادل مکرر باشند.

    ۳. نمایش پروفایل کاربر

    نمایش پروفایل کاربر شامل نشان دادن اطلاعات ثابتی مانند نام، تصویر پروفایل و احتمالاً بیوگرافی است. استفاده از `React.memo` تضمین می‌کند که کامپوننت فقط زمانی رندر مجدد می‌شود که داده‌های کاربر واقعاً تغییر کنند، نه در هر به‌روزرسانی کامپوننت والد.

    import React, { memo } from 'react';
    
    const UserProfile = ({ user }) => {
     console.log('UserProfile rendered');
     return (
     

    {user.name}

    Profile

    {user.bio}

    ); }; export default memo(UserProfile);

    این امر به ویژه زمانی مفید است که `UserProfile` بخشی از یک داشبورد یا اپلیکیشن بزرگتر و به طور مکرر در حال به‌روزرسانی باشد که در آن داده‌های خود کاربر اغلب تغییر نمی‌کنند.

    اشتباهات رایج و نحوه جلوگیری از آنها

    در حالی که React.memo یک ابزار بهینه‌سازی ارزشمند است، مهم است که از اشتباهات رایج آگاه باشید و از آنها اجتناب کنید:

    پروفایل کردن اپلیکیشن شما

    بهترین راه برای تعیین اینکه آیا React.memo واقعاً عملکرد را بهبود می‌بخشد، پروفایل کردن اپلیکیشن شماست. ری‌اکت چندین ابزار برای پروفایل کردن فراهم می‌کند، از جمله React DevTools Profiler و React.Profiler API.

    React DevTools Profiler به شما امکان می‌دهد ردپاهای عملکرد اپلیکیشن خود را ضبط کرده و کامپوننت‌هایی را که به طور مکرر رندر مجدد می‌شوند، شناسایی کنید. React.Profiler API به شما امکان می‌دهد زمان رندر کامپوننت‌های خاص را به صورت برنامه‌نویسی اندازه‌گیری کنید.

    با پروفایل کردن اپلیکیشن خود، می‌توانید کامپوننت‌هایی را که بیشترین سود را از مموایزیشن می‌برند شناسایی کرده و اطمینان حاصل کنید که React.memo واقعاً عملکرد را بهبود می‌بخشد.

    نتیجه‌گیری

    React.memo یک ابزار قدرتمند برای بهینه‌سازی عملکرد کامپوننت‌های ری‌اکت است. با جلوگیری از رندرهای مجدد غیرضروری، می‌تواند سرعت و واکنش‌پذیری اپلیکیشن‌های شما را بهبود بخشد و منجر به تجربه کاربری بهتری شود. با این حال، مهم است که از React.memo با دقت استفاده کنید و اپلیکیشن خود را پروفایل کنید تا اطمینان حاصل کنید که واقعاً عملکرد را بهبود می‌بخشد.

    با درک مفاهیم و تکنیک‌های مورد بحث در این پست وبلاگ، می‌توانید به طور مؤثر از React.memo و تکنیک‌های مرتبط برای ساخت اپلیکیشن‌های ری‌اکت با کارایی بالا برای مخاطبان جهانی استفاده کنید و اطمینان حاصل کنید که اپلیکیشن‌های شما برای کاربران در سراسر جهان سریع و واکنش‌گرا هستند.

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

    مطالعه بیشتر و منابع