کامپوننت‌های تابعی در React — استاندارد مدرن توسعه

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

Functional Component — روشی برای ایجاد کامپوننت‌های React با استفاده از توابع معمولی JavaScript است که پس از انتشار React 16.8 و ظهور هوک‌ها به استاندارد تبدیل شد. کامپوننت‌های تابعی props دریافت می‌کنند و عناصر React را برمی‌گردانند، بدون نیاز به ارث‌بری از React.Component. طبق داده‌های React, 2024، 97% کامپوننت‌های جدید در اکوسیستم React به صورت توابع نوشته می‌شوند.

نکات اصلی

  • Functional Component — یک تابع معمولی JavaScript که props دریافت می‌کند و JSX برمی‌گرداند، بدون extends Component.
  • هوک‌ها (useState, useEffect, useContext) به کامپوننت‌های تابعی دسترسی کامل به حالت و چرخه حیات می‌دهند.
  • خوانایی — کامپوننت‌های تابعی کوتاه‌تر از کلاسی هستند، بدون سازنده، bind و متدهای اضافی چرخه حیات.
  • عملکرد — React کامپوننت‌های تابعی را از طریق memoization و مقداردهی اولیه تنبل بهینه می‌کند.
  • توصیه React — همه پروژه‌های جدید فقط از کامپوننت‌های تابعی با هوک‌ها استفاده کنند.

Functional Component چیست؟

Functional Component (کامپوننت تابعی) — کامپوننت React است که به صورت تابع تعریف می‌شود، شی props را دریافت می‌کند و عنصر React برمی‌گرداند. قبل از React 16.8 چنین کامپوننت‌هایی stateless (بدون حالت) نامیده می‌شدند، زیرا نمی‌توانستند حالت داخلی را مدیریت کنند.

با ظهور هوک‌ها در React 16.8 (فوریه 2019) کامپوننت‌های تابعی به حالت (useState)، اثرات جانبی (useEffect)، زمینه (useContext) و مراجع (useRef) دسترسی یافتند. اصطلاح «stateless» منسوخ شده است — کامپوننت‌های تابعی مدرن به طور کامل حالت را مدیریت می‌کنند.

React به طور رسمی کامپوننت‌های تابعی را به عنوان روش اصلی ایجاد کامپوننت‌ها توصیه می‌کند. تمام مستندات در react.dev، مثال‌ها، آموزش‌ها و APIهای جدید (Server Components, Actions) بر روی رویکرد تابعی ساخته شده‌اند. کامپوننت‌های کلاسی حذف نشده‌اند، اما قابلیت‌های جدید React فقط از طریق هوک‌ها در دسترس هستند.

ایجاد کامپوننت تابعی

ساده‌ترین کامپوننت تابعی — تابعی است که JSX برمی‌گرداند. آن props را به عنوان آرگومان دریافت می‌کند، نیاز به سازنده، فراخوانی super یا binding this ندارد. props در دسترس هستند مستقیماً از طریق آرگومان تابع — بدون this.props.

js
// Functional component without state
function Greeting({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Arrow function (common variant)
const Greeting = ({ name }) => (
  <h1>Hello, {name}!</h1>
);

کامپوننت با حالت

برای افزودن حالت از useState استفاده کنید. هوک یک چندتایی از دو مقدار برمی‌گرداند: حالت فعلی و تابع setter. بر خلاف this.setState کلاسی، useState مقدار را به طور کامل جایگزین می‌کند، نه اینکه با مقدار قبلی ادغام کند.

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

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Increment
      </button>
    </div>
  );
}

هوک‌ها در کامپوننت‌های تابعی

هوک‌ها اساس React مدرن هستند. هر هوک یک وظیفه خاص را حل می‌کند: useState — حالت، useEffect — اثرات جانبی، useContext — دسترسی به زمینه، useRef — مراجع به عناصر DOM، useCallback و useMemo — memoization.

useEffect برای اثرات جانبی

useEffect همزمان جایگزین componentDidMount، componentDidUpdate و componentWillUnmount می‌شود. آرگومان اول — callback با اثر، دوم — آرایه وابستگی‌ها. اگر آرایه خالی باشد، اثر یک بار پس از mount اجرا می‌شود. اگر وابستگی‌ها مشخص شده‌اند — با هر تغییر در هر یک از آنها.

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

function UserData({ userId }) {
  const [user, setUser] = useState(null);

  useEffect(() => {
    let cancelled = false;

    fetch(`/api/users/${userId}`)
      .then(res => res.json())
      .then(data => {
        if (!cancelled) setUser(data);
      });

    // Cleanup - analog of componentWillUnmount
    return () => { cancelled = true; };
  }, [userId]); // Dependency

  return <div>{user?.name}</div>;
}

هوک‌های سفارشی

مزیت اصلی کامپوننت‌های تابعی — استفاده مجدد از منطق از طریق هوک‌های سفارشی است. اگر در کامپوننت کلاسی منطق بین componentDidMount و componentDidUpdate تکرار می‌شد، در کامپوننت تابعی به یک تابع جداگانه با پیشوند use منتقل می‌شود. هوک‌های سفارشی — جایگزین اصلی HOC و render props هستند.

ترکیب به جای وراثت

React برای استفاده مجدد از کد بین کامپوننت‌ها ترکیب را توصیه می‌کند، نه وراثت را. کامپوننت‌های تابعی برای ترکیب ایده‌آل هستند: یک کامپوننت می‌تواند شامل چندین کامپوننت دیگر باشد، props و children را به آنها منتقل کند.

الگوی children — وقتی کامپوننت عناصر فرزند را از طریق prop children دریافت می‌کند — به طور طبیعی پیاده‌سازی می‌شود: function Layout({ children }). مشابه slots در Vue از طریق props-کامپوننت‌های نام‌گذاری شده پیاده‌سازی می‌شود: function Page({ header, sidebar, content }).

وراثت در React عملاً استفاده نمی‌شود. حتی کامپوننت‌های کلاسی که از نظر فنی extends را پشتیبانی می‌کنند، به ندرت سلسله‌مراتب عمیق‌تر از یک سطح تشکیل می‌دهند. کامپوننت‌های تابعی با ترکیب نیازهای استفاده مجدد از کد را بدون وراثت کاملاً پوشش می‌دهند.

بهینه‌سازی عملکرد

کامپوننت‌های تابعی مکانیسم‌های بهینه‌سازی داخلی دارند. React.memo — مشابه PureComponent برای توابع: از رندر مجدد جلوگیری می‌کند اگر props تغییر نکرده باشند (مقایسه سطحی). useMemo نتیجه محاسبات را بین رندرها کش می‌کند.

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

// React.memo - memoize component
const ExpensiveList = React.memo(({ items }) => {
  return <ul>
    {items.map(item =>
      <li key={item.id}>{item.name}</li>
    )}
  </ul>;
});

// useMemo - caching result
function Dashboard({ transactions }) {
  const summary = useMemo(() => {
    return transactions.reduce((acc, t) => acc + t.amount, 0);
  }, [transactions]);

  return <p>Total: {summary}</p>;
}

useCallback توابع callback را memoize می‌کند تا در هر رندر دوباره ایجاد نشوند. این هنگام ارسال توابع به کامپوننت‌های فرزند که در React.memo پیچیده شده‌اند حیاتی است: بدون useCallback کامپوننت فرزند هر بار رندر می‌شود، زیرا reference به تابع تغییر می‌کند.

مقایسه کامپوننت‌های تابعی و کلاسی

تفاوت بین رویکردها فراتر از نحو است. کامپوننت‌های تابعی — یک closure هستند: حالت و اثرات به یک رندر خاص متصل هستند. کامپوننت‌های کلاسی — this هستند: حالت همیشه از this.state گرفته می‌شود که ممکن است در زمان اجرای callback ناهمگام منسوخ شده باشد.

جنبهتابعیکلاسی
حالتuseState (منزوی)this.state + this.setState
اثراتuseEffect با وابستگی‌هاcomponentDidMount + componentDidUpdate
زمینهuseContextContext.Consumer یا static contextType
بهینه‌سازیReact.memo + useMemoPureComponent + shouldComponentUpdate
استفاده مجدد از منطقهوک‌های سفارشیHOC / Render props
thisنداردbind در سازنده

کامپوننت‌های تابعی جریان اجرای خطی را فراهم می‌کنند. در کامپوننت کلاسی منطق مرتبط اغلب در چندین متد چرخه حیات پخش می‌شود. به عنوان مثال، اشتراک WebSocket در componentDidMount تنظیم می‌شود و در componentWillUnmount حذف می‌شود. در کامپوننت تابعی هر دو عملیات — در یک useEffect با تابع بازگشتی پاکسازی.

TypeScript و کامپوننت‌های تابعی

TypeScript با کامپوننت‌های تابعی طبیعی‌تر از کلاس‌ها کار می‌کند. نوع‌دهی props — یک اینترفیس برای آرگومان تابع. نوع مقدار بازگشتی — JSX.Element یا ReactNode. useState به طور خودکار نوع را از مقدار اولیه استنتاج می‌کند.

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

interface ButtonProps {
  label: string;
  variant?: 'primary' | 'secondary';
  onClick: () => void;
}

const Button: React.FC<ButtonProps> =
  ({ label, variant = 'primary', onClick }) => (
    <button
      className={`btn btn-${variant}`}
      onClick={onClick}
    >
      {label}
    </button>
  );

TypeScript مدرن امکان نوع‌دهی useReducer با انواع union تفکیک‌شده، Generics در هوک‌های سفارشی و بررسی دقیق children از طریق React.PropsWithChildren را فراهم می‌کند. کامپوننت‌های تابعی با TypeScript امنیت کامل نوع را بدون انتزاعات اضافی ارائه می‌دهند.

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

چرا React کامپوننت‌های تابعی را توصیه می‌کند؟

کامپوننت‌های تابعی ساده‌تر هستند: سازنده، bind، this و متدهای پراکنده چرخه حیات وجود ندارد. هوک‌ها امکان گروه‌بندی منطق مرتبط را فراهم می‌کنند. React منابع خود را روی توسعه هوک‌ها سرمایه‌گذاری می‌کند، نه کلاس‌ها. Server Components و ویژگی‌های جدید فقط در توابع در دسترس هستند.

آیا می‌توان از setInterval در کامپوننت تابعی استفاده کرد؟

بله، از طریق useEffect با تایمر در داخل و تابع پاکسازی برای clearInterval. به closure توجه کنید: اگر شمارنده را تیک می‌زنید، از setState به صورت تابعی استفاده کنید: setCount(c => c + 1)، تا به مقدار قدیمی در closure وابسته نباشید.

چگونه props قبلی را در کامپوننت تابعی دریافت کنیم؟

از useRef برای ذخیره مقدار قبلی استفاده کنید. ref را در useEffect پس از هر رندر به‌روزرسانی کنید. برای مقایسه بصری هوک سفارشی usePrevious کمک می‌کند: const prev = usePrevious(value);

تفاوت React.memo و useMemo چیست؟

React.memo — HOC برای memoization کل کامپوننت: از رندر مجدد جلوگیری می‌کند اگر props تغییر نکرده باشند. useMemo — هوک برای memoization یک مقدار خاص در داخل کامپوننت: نتیجه تابع را بین رندرها بر اساس آرایه وابستگی‌ها کش می‌کند.

چگونه getDerivedStateFromProps را در کامپوننت تابعی شبیه‌سازی کنیم؟

ساده‌ترین راه — useState با مقداردهی اولیه از props + useEffect با وابستگی به props برای همگام‌سازی. برای موارد نادر React توصیه می‌کند: از کلید (key) برای بازآفرینی اجباری کامپوننت هنگام تغییر داده‌های ورودی استفاده کنید.

خلاصه

  • Functional Component — استاندارد مدرن React: تابعی که props دریافت می‌کند و JSX برمی‌گرداند.
  • هوک‌ها (useState, useEffect) به کامپوننت‌های تابعی حالت، اثرات و زمینه را بدون کلاس می‌دهند.
  • ترکیب از طریق children و هوک‌های سفارشی جایگزین وراثت و الگوهای HOC می‌شود.
  • React.memo و useMemo بهینه‌سازی عملکرد کامپوننت‌های تابعی را تضمین می‌کنند.
  • TypeScript با کامپوننت‌های تابعی نوع‌دهی دقیق props و استنتاج خودکار انواع را فراهم می‌کند.
  • useEffect همه متدهای چرخه حیات کامپوننت‌های کلاسی را در یک مکان جایگزین می‌کند.
  • هوک‌های سفارشی امکان استخراج و استفاده مجدد از منطق بین کامپوننت‌ها را بدون HOC فراهم می‌کنند.

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

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

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

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