برنامه نویسی

واکنش: الگوهای طراحی | اجزای ظرف

در دنیای React، یک الگوی طراحی به نام Container Components وجود دارد. اگر یک برنامه‌نویس React مبتدی یا متوسط ​​هستید، ممکن است عادت داشته باشید که هر مؤلفه فرزند داده‌های خود را بارگیری کند. به طور معمول، شما از قلاب هایی مانند useState و useEffect همراه با کتابخانه هایی مانند Axios یا Fetch برای دریافت اطلاعات از یک سرور. این کار می کند، اما زمانی که چندین مؤلفه فرزند نیاز دارند منطق یکسانی را به اشتراک بگذارند، ممکن است کثیف شود. اینجاست که اجزای ظرف وارد می شوند.

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

ایده اصلی

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

یک مثال ساده: CurrentUserLoader

بیایید با یک مثال ساده شروع کنیم. فرض کنید یک داریم CurrentUserLoader مؤلفه ای که داده های کاربر فعلی را بارگیری می کند و آن را به a ارسال می کند UserInfo جزء.

import React, { useState, useEffect } from 'react';
import axios from 'axios';

export const CurrentUserLoader = ({ children }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await axios.get('/current-user');
      setUser(response.data);
    };
    fetchData();
  }, []);

  return (
    <>
      {React.Children.map(children, child => {
        if (React.isValidElement(child)) {
          return React.cloneElement(child, { user });
        }
        return child;
      })}
    >
  );
};
وارد حالت تمام صفحه شوید

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

در این مثال، CurrentUserLoader داده‌های کاربر فعلی را واکشی می‌کند و آن‌ها را به‌عنوان یک به فرزندان خود ارسال می‌کند user پشتیبانی این UserInfo سپس کامپوننت می تواند از این پایه برای نمایش اطلاعات کاربر استفاده کند.

انعطاف پذیرتر کردن: UserLoader

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

import React, { useState, useEffect } from 'react';
import axios from 'axios';

export const UserLoader = ({ userId, children }) => {
  const [user, setUser] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await axios.get(`/users/${userId}`);
      setUser(response.data);
    };
    fetchData();
  }, [userId]);

  return (
    <>
      {React.Children.map(children, child => {
        if (React.isValidElement(child)) {
          return React.cloneElement(child, { user });
        }
        return child;
      })}
    >
  );
};
وارد حالت تمام صفحه شوید

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

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

Going Generic: ResourceLoader

ما می توانیم این مفهوم را حتی با ایجاد یک عمومی فراتر ببریم ResourceLoader مؤلفه ای که می تواند هر نوع منبعی را از سرور بارگیری کند.

import React, { useState, useEffect } from 'react';
import axios from 'axios';

export const ResourceLoader = ({ resourceUrl, resourceName, children }) => {
  const [state, setState] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const response = await axios.get(resourceUrl);
      setState(response.data);
    };
    fetchData();
  }, [resourceUrl]);

  return (
    <>
      {React.Children.map(children, child => {
        if (React.isValidElement(child)) {
          return React.cloneElement(child, { [resourceName]: state });
        }
        return child;
      })}
    >
  );
};
وارد حالت تمام صفحه شوید

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

با ResourceLoader، می توانید هر منبعی را با تعیین URL و نام آن بارگیری کنید. این باعث می شود که این جزء بسیار قابل استفاده مجدد باشد.

انعطاف پذیری نهایی: منبع داده

در نهایت، اجازه دهید یک را ایجاد کنیم DataSource مؤلفه ای که حتی نمی داند داده هایش از کجا آمده است. به جای اینکه منطق واکشی داده ها را کدگذاری کنیم، تابعی را ارسال می کنیم که داده ها را برمی گرداند.

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

export const DataSource = ({ getDataFunction, resourceName, children }) => {
  const [state, setState] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      const data = await getDataFunction();
      setState(data);
    };
    fetchData();
  }, [getDataFunction]);

  return (
    <>
      {React.Children.map(children, child => {
        if (React.isValidElement(child)) {
          return React.cloneElement(child, { [resourceName]: state });
        }
        return child;
      })}
    >
  );
};
وارد حالت تمام صفحه شوید

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

با DataSource، می توانید داده ها را از هر منبعی بارگیری کنید – خواه یک API، ذخیره سازی محلی یا چیز دیگری باشد – با ارسال تابعی که داده ها را برمی گرداند.

نتیجه

کامپوننت‌های Container یک الگوی قدرتمند در React هستند که به شما در مدیریت بارگذاری داده‌ها و منطق اشتراک‌گذاری در چندین مؤلفه کمک می‌کنند. با انتزاع کردن منطق واکشی داده در اجزای کانتینری مانند CurrentUserLoader، UserLoader، ResourceLoader، و DataSource، می توانید کد خود را تمیزتر و قابل نگهداری تر کنید. این تفکیک نگرانی‌ها به اجزای فرزند شما اجازه می‌دهد تا تنها بر روی رندر تمرکز کنند و درک و گسترش برنامه شما را آسان‌تر می‌کند.


React: Design Patterns یک دوره آموزشی توسط Shaun Wassell است که می توانید آن را در LinkedIn Learning دنبال کنید.

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

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

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

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