Anophel-آنوفل 3 راه برای رندر کردن دیتاهای بزرگ در React

3 راه برای رندر کردن دیتاهای بزرگ در React

تاریخ انتشار:
React
زمان مطالعه: 12 دقیقه

همانطور که برنامه های کاربردی وب به طور فزاینده ای پیچیده می شوند، ما باید راه های کارآمدی برای بهینه سازی عملکرد و ارائه مجموعه داده های بزرگ پیدا کنیم. هنگام کار با یک مجموعه داده بزرگ در یک برنامه React، رندر کردن همه داده ها به طور همزمان می تواند منجر به عملکرد ضعیف و زمان بارگذاری کند شود.

 

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

 

  • React Virtuoso
  • React Window
  • react-infinite-scroller

 

React Virtuoso

React Virtuoso یک کتابخانه لیست مجازی شده برای React است که رندر سریع و کارآمد مجموعه داده های بزرگ را امکان پذیر می کند. و بسیار قابل تنظیم است و ما می توانیم از آن برای ارائه ساختار داده های ساده و پیچیده استفاده کنیم.

 

React Virtuoso از تکنیک windowing استفاده می‌کند که فقط عناصر را روی صفحه نمایش می‌دهد و در نتیجه زمان بارگذاری سریع‌تر و عملکرد بهتر را به همراه دارد.

در اینجا نحوه استفاده از React Virtuoso در برنامه خود در دو مرحله آورده ایم:

 

ابتدا کتابخانه Virtuoso را نصب کنید:

 

npm install react-virtuoso

 

بعد، از این کامپوننت در برنامه خود استفاده کنید:

 

import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { Virtuoso } from 'react-virtuoso'
const App = () => (
  <Virtuoso
    style={{ height: '600px',
    background: '#f8f8f8'
   }}
    totalCount={10000}
    itemContent={index => (
      <div style={{ 
        background: index % 2 === 0 ? '#ffbb00' : '#ffcc33',
        color: '#333',
        padding: '10px',
        fontSize: '16px',
        fontFamily: 'Arial, sans-serif',
        border: '1px solid #ccc',
        borderRadius: '4px',
        margin: '5px 0'
      }}>
        Item {index}
      </div>
    )}
  />
)
export default App;
ReactDOM.render(<App />, document.getElementById('root'))

 

در کد بالا، کامپوننت Virtuoso را از کتابخانه react-virtuoso وارد می کنیم.
سپس یک کامپوننت تابعی به نام App تعریف می کنیم که کامپوننت Virtuoso را برمی گرداند.

 

کامپوننت Virtuoso دارای چندین ویژگی است:

 

style: استایل کامپوننت، از جمله ارتفاع و رنگ پس‌زمینه آن را تنظیم می‌کند.
totalCount: تعداد کل موارد موجود در لیست را تنظیم می کند. در این مورد 10000.
itemContent: یک پارامتر index دریافت می کند و کد JSX را برای ارائه آیتم در آن شاخص برمی گرداند.


در این حالت، تابع یک تگ div حاوی متن "Item" و به دنبال آن شماره index را ارائه می دهد. Style prop رنگ پس زمینه، اندازه قلم، فونت، border, border radius و مارجین تگ div را بر اساس فرد یا زوج بودن index تنظیم می کند.

 

ما می توانیم تصاویر را نیز به لیست خود اضافه کنیم:

 

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { Virtuoso } from 'react-virtuoso';
const App = () => {
  const [images, setImages] = React.useState([]);
  // Fetch random images from Unsplash on component mount
  React.useEffect(() => {
    const fetchImages = async () => {
      const response = await fetch(
        'https://api.unsplash.com/photos/random?count=100',
        {
          headers: {
            Authorization: 'Client-ID <UNSPLASH ACCESS KEY>',
          },
        }
      );
      const data = await response.json();
      const urls = data.map(item => item.urls.thumb);
      setImages(urls);
    };
    fetchImages();
  }, []);
  return (
    <Virtuoso
      style={{ 
        height: '400px',
        background: '#fff'
      }}
      totalCount={10000}
      itemContent={index => (
        <div style={{ 
          background: index % 2 === 0 ? '#ffbb00' : '#ffcc33',
          color: '#333',
          padding: '10px',
          fontSize: '16px',
          fontFamily: 'Arial, sans-serif',
          border: '1px solid #ccc',
          borderRadius: '4px',
          margin: '5px 0',
          display: 'flex',
          alignItems: 'center'
        }}>
          <img src={images[index % 100]} alt={`Item ${index}`} style={{ marginRight: '10px', width: '50px', height: '50px', borderRadius: '50%' }} />
          Item {index}
        </div>
      )}
    />
  );
};
export default App;
ReactDOM.render(<App />, document.getElementById('root'));

 

ممکن است متوجه شوید که این کد با کد قبلی ما تفاوت چندانی ندارد. ما یک برنامه کامپوننت تابعی را با استفاده از useState و useEffect Hooks تعریف می کنیم. سپس یک متغیر state به نام images تعریف می کنیم و با استفاده از useState Hook مقدار اولیه آن را روی یک آرایه خالی قرار می دهیم.

 

ما تابعی به نام fetchImages تعریف می کنیم که از fetch API برای درخواست GET به Unsplash API برای بازیابی 100 تصویر تصادفی استفاده می کند. سپس، روی داده‌های پاسخ نگاشت می‌کنیم و URL thumb را برای هر تصویر استخراج می‌کنیم و با استفاده از تابع setImages، متغیر state تصاویر را روی آرایه URLهای حاصل تنظیم می‌کنیم.

 

در مرحله بعد، از useEffect Hook برای فراخوانی تابع fetchImages یک بار، زمانی که کامپوننت مانت می‌شود، استفاده می‌کنیم، زیرا فقط یک بار می‌خواهیم تصاویر را fetch کنیم. مانند قبل، یک کامپوننت Virtuoso را برمی‌گردانیم که دارای ویژگی‌های زیر است:

 

style، که برای ایجاد رنگ پس‌زمینه و ارتفاع برای کامپوننت Virtuoso ما، با ویژگی ارتفاع 400 پیکسل و ویژگی پس‌زمینه fff# تنظیم شده است.
totalCount
itemContent
 

این بار کد JSX که از تابع itemContent برمی گردانیم یک تگ div است که حاوی یک تگ img و مقداری متن است. ویژگی src تگ img به URL تصویر مربوط به مقدار index فعلی تنظیم می شود که با استفاده از عملگر مدول (%) از متغیر state تصاویر بازیابی می شود.

 

ویژگی مثبت Virtuoso:
Virtuoso در ارائه مجموعه داده های بزرگ بسیار کارآمد است.
بسیار قابل تنظیم است.
این پشتیبانی از اندازه آیتم های پویا را فراهم می کند.
عملکرد خوب.


معایب Virtuoso:
اسناد محدود.
بدون پشتیبانی از لیست های تودرتو.

 

React Window

کتابخانه بعدی که به آن نگاه خواهیم کرد React Window است، یک کتابخانه لیست مجازی شده برای React که از تکنیک windowing مشابه React Virtuoso استفاده می کند.

React Window به نوعی نسخه به روز شده React Virtualized است. همچنین کارایی بالایی دارد و می توان از آن برای ارائه کارآمد مجموعه داده های بزرگ استفاده کرد. React Window مجموعه‌ای از APIها را در اختیار ما قرار می‌دهد که می‌توانیم از آنها برای سفارشی کردن رفتار لیست خود استفاده کنیم و آن را به ابزاری انعطاف‌پذیر و قدرتمند تبدیل کنیم.

 

React Window را نصب کنید:

 

npm install --save react-window

 

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

 

کتابخانه Faker را با استفاده از npm نصب کنید:

 

npm install faker

 

سپس آن را در کد خود پیاده سازی کنید:

 

import React from 'react';
import { FixedSizeList } from 'react-window';
import { faker } from '@faker-js/faker';
const App = () => {
  const data = Array.from({ length: 10000 }).map(() => ({
    name: faker.name.firstName(),
    email: faker.internet.email(),
  }));
  const Row = ({ index, style }) => {
    const isEvenRow = index % 2 === 0;
    const backgroundColor = isEvenRow ? '#F9A03F' : '#FDDB3A';
    const textColor = isEvenRow ? '#FFFFFF' : '#4A4A4A';
    const rowStyle = {
      ...style,
      backgroundColor,
      color: textColor,
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '0 16px',
    };
    return (
      <div style={rowStyle}>
        <p>{data[index].name}</p>
        <p>{data[index].email}</p>
      </div>
    );
  };
  return (
    <FixedSizeList height={600} width={1200} itemSize={50} itemCount={data.length}>
      {Row}
    </FixedSizeList>
  );
};
export default App;

 

ما کامپوننت FixedSizeList را از کتابخانه react-window و کتابخانه faker را وارد می کنیم که برای تولید داده های فیک برای اهداف آزمایشی استفاده می شود.

 

پس از وارد کردن کتابخانه های لازم، یک کامپوننت تابعی به نام App تعریف می کنیم که آرایه ای از 10000 آبجکت را ایجاد می کند. هر آبجکت شامل یک نام و یک ویژگی ایمیل است. مقادیر آنها با استفاده از کتابخانه faker تولید می شود.

 

در مرحله بعد، یک کامپوننت تابعی جدید به نام Row تعریف می‌کنیم، که یک نمایه و استایل را می‌گیرد و هر ردیف از داده‌ها را رندر می‌کند. نام و داده‌های ایمیل برای فهرست مربوطه را از آرایه داده‌ای که قبلاً تعریف کردیم، بازیابی می‌کند و آن را در یک تگ div با استفاده از استایل پاس داده شده ارائه می‌کند.

 

در نهایت، یک کامپوننت FixedSizeList را از کتابخانه react-window برمی گردانیم که موارد زیر را شامل می شود:

پراپس های height و width ، که اندازه لیست را تعیین می کند.
itemSize که height هر ردیف را تعیین می کند.
itemCount، که تعداد کل موارد موجود در لیست را تعیین می کند.


تابعی برای رندر کردن هر سطر از داده ها، که روی کامپوننت Row که قبلا تعریف کردیم تنظیم می شود.

 

با استفاده از کامپوننت VariableSizedList می توانیم لیست هایی با اندازه متغیر ایجاد کنیم:

 

import React from 'react';
import { VariableSizeList } from 'react-window';
import { faker } from '@faker-js/faker';
const App = () => {
  const data = Array.from({ length: 10000 }).map(() => ({
    name: faker.name.firstName(),
    email: faker.internet.email(),
  }));
  const Row = ({ index, style }) => {
    const isEvenRow = index % 2 === 0;
    const backgroundColor = isEvenRow ? '#F9A03F' : '#FDDB3A';
    const textColor = isEvenRow ? '#FFFFFF' : '#4A4A4A';
    const rowStyle = {
      ...style,
      backgroundColor,
      color: textColor,
      display: 'flex',
      justifyContent: 'space-between',
      alignItems: 'center',
      padding: '0 16px',
    };
    return (
      <div style={rowStyle}>
        <p>{data[index].name}</p>
        <p>{data[index].email}</p>
      </div>
    );
  };
  const getItemSize = index => {
    const randomHeight = Math.floor(Math.random() * 100) + 50;
    return randomHeight;
  };
  return (
    <VariableSizeList height={600} width={1200} itemCount={data.length} itemSize={getItemSize}>
      {Row}
    </VariableSizeList>
  );
};
export default App;

 

در این مثال، تابع getItemSize یک ارتفاع تصادفی بین 50 تا 150 پیکسل برای هر ردیف محاسبه می کند. شما می توانید محاسبه را برای ایجاد محدوده های مختلف اندازه، یا حتی برای تولید اندازه های مختلف بر اساس داده های هر ردیف تنظیم کنید.

 

توجه داشته باشید که با تنوع بسیار زیاد در ارتفاع ردیف، عملکرد پیمایش ممکن است تحت تأثیر قرار گیرد، زیرا کامپوننت فهرست باید هر ردیف را در حین پیمایش محاسبه و قرار دهد.

 

ویژگی های مثبت React Window:
با عملکرد بالا
قابل تنظیم
پشتیبانی از اندازه آیتم های پویا
مستندات خوب


معایب پنجره React Window:
پشتیبانی محدود از لیست های تو در تو
بدون پشتیبانی داخلی برای بازیابی اسکرول

 

react-infinite-scroller

react-infinite-scroller کتابخانه ای است که به شما امکان می دهد مجموعه داده های بزرگ را به روشی کارآمد ارائه دهید. این کتابخانه همچنین از تکنیک windowing  یا مجازی سازی استفاده می کند، که در آن تنها بخش قابل مشاهده از داده ها ارائه می شود و بقیه بر اساس درخواست بارگیری می شوند و کاربر در حال پیمایش است.

 

ما از کتابخانه Faker برای تولید مجموعه داده های بزرگ در اینجا نیز استفاده خواهیم کرد. نصبش کنید:

 

npm install faker

 

سپس react-infinite-scroller را نصب کنید:

 

npm i react-infinite-scroller

 

در مرحله بعد، کامپوننتی به نام UserList ایجاد می کنیم که لیستی از کاربران تولید شده توسط کتابخانه Faker را ارائه می دهد.

 

import React, { useState } from "react";
import InfiniteScroll from "react-infinite-scroller";
import { faker } from "@faker-js/faker";
function UserList() {
  const [users, setUsers] = useState([]);
  const loadMore = (page) => {
    const newUsers = [];
    for (let i = 0; i < 20; i++) {
      newUsers.push({
        name: faker.name.findName(),
        email: faker.internet.email(),
        phone: faker.phone.phoneNumber(),
      });
    }
    setUsers([...users, ...newUsers]);
  };
  const rowStyle = {
    display: "flex",
    justifyContent: "space-between",
    alignItems: "center",
    padding: "10px",
    backgroundColor: "#f1f1f1",
    borderBottom: "1px solid #ccc",
    fontSize: "16px",
    color: "#333",
  };
  const nameStyle = {
    fontWeight: "bold",
    color: "#38a3a5",
  };
  const emailStyle = {
    fontStyle: "italic",
    color: "#ff7f50",
  };
  const phoneStyle = {
    color: "#6a5acd",
  };
  return (
    <InfiniteScroll
      pageStart={0}
      loadMore={loadMore}
      hasMore={true}
      loader={<div className="loader" key={0}>Loading ...</div>}
    >
      <ul style={{ listStyle: "none", margin: "0", padding: "0" }}>
        {users.map((user, index) => (
          <li key={index} style={rowStyle}>
            <div style={nameStyle}>{user.name}</div>
            <div style={emailStyle}>{user.email}</div>
            <div style={phoneStyle}>{user.phone}</div>
          </li>
        ))}
      </ul>
    </InfiniteScroll>
  );
}
export default UserList;

 

بیایید این را تجزیه کنیم. در کامپوننت UserList، ما از useState Hook برای مدیریت state آرایه کاربران استفاده می کنیم. تابع loadMore هم 20 کاربر جدید تولید می کند و آنها را به آرایه کاربران موجود اضافه می کند.

 

وقتی کامپوننت مانت می‌شود، کامپوننت InfiniteScroll رندر می‌شود. صفحه شروع شماره صفحه را نشان می دهد که داده ها از آنجا بارگذاری می شوند.

 

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

 

پراپ hasMore نشان می دهد که آیا داده های بیشتری برای بارگذاری وجود دارد یا خیر. در مورد ما، می‌خواهیم آن را روی true تنظیم کنیم زیرا می‌خواهیم داده‌های بیشتری را به‌طور نامحدود بارگذاری کنیم. loader prop یک عنصر React است که در حین بارگذاری داده ها رندر می شود. ما یک لودر ساده اضافه کرده ایم که پیام بارگیری را نشان می دهد.

 

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

برای استایل‌سازی، چندین استایل را با استفاده از آبجکت‌های جاوا اسکریپت تعریف می‌کنیم و با استفاده از ویژگی style آنها را به تگ های مربوطه اعمال می‌کنیم. شی rowStyle یک رنگ پس‌زمینه خاکستری روشن با border خاکستری تیره‌تر و رنگ متن سفید اعمال می‌کند، در حالی که آبجکت  های nameStyle، emailStyle و phoneStyle به ترتیب رنگ‌ها و استایل های متن متفاوتی را برای قسمت‌های نام، ایمیل و شماره تلفن تعریف می‌کنند.

 

مزایای استفاده از react-infinite-scroller:
عملکرد بهبود یافته: مزیت اصلی استفاده از react-infinite-scroller عملکرد بهبود یافته آن است. با رندر کردن تنها بخش قابل مشاهده از داده ها، تعداد گره های DOM کاهش می یابد و در نتیجه سرعت رندر افزایش می یابد.
کاهش مصرف حافظه: از آنجایی که تنها بخش قابل مشاهده از داده ها ارائه می شود، مصرف حافظه را به میزان قابل توجهی کاهش می دهد
پیمایش بی‌نهایت: کتابخانه پیمایش بی‌نهایت خارج از جعبه را فراهم می‌کند، به این معنی که داده‌ها را می‌توان به صورت پویا و بدون نیاز به بازخوانی صفحه یا بارگذاری دستی بارگیری کرد.
استفاده آسان: react-infinite-scroller برای استفاده آسان است و به طور یکپارچه با برنامه های React ادغام می شود.


معایب استفاده از react-infinite-scroller:
پیاده سازی پیچیده: پیاده سازی اسکرول بی نهایت می تواند پیچیده باشد، به خصوص برای مبتدیان. شما باید اطمینان حاصل کنید که داده ها به روشی کارآمد بارگذاری می شوند و در عین حال وضعیت کامپوننت را پیگیری می کنید
مشکل ارتفاع پویا: react-infinite-scroller مشکل ارتفاع پویا را بررسی نمی کند. اگر موارد موجود در لیست دارای ارتفاع های متفاوتی باشند، کتابخانه نمی تواند ارتفاع کل لیست را به طور دقیق محاسبه کند و در نتیجه موقعیت اسکرول نادرست است.

 

نتیجه

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

در این مقاله، کتابخانه‌های مختلف لیست مجازی‌سازی شده موجود برای React را بررسی کرده‌ایم، از جمله React Virtuoso، React Window و react-infinite-scroll. هر کتابخانه مزایا و معایب خود را دارد و انتخاب کتابخانه بستگی به مورد استفاده خاص دارد. با استفاده از این کتابخانه های لیست مجازی شده، می توانید عملکرد برنامه های React خود را به میزان قابل توجهی بهبود بخشید و تجربه کاربری روان تری ارائه دهید.

#ری_اکت #react #داده_های_بزرگ #دیتای_بزرگ