You are currently viewing آموزش کامل و حرفه‌ای React JSX | مثال‌های کاربردی و نکات پیشرفته

آموزش کامل و حرفه‌ای React JSX | مثال‌های کاربردی و نکات پیشرفته

آموزش حرفه‌ای React JSX: از اصول تا الگوهای پیشرفته

JSX یک سینتکس شبیه HTML است که داخل جاوااسکریپت استفاده می‌شود و به‌صورت Declarative رابط کاربری را توصیف می‌کند. این آموزش از مبانی تا تکنیک‌های حرفه‌ای (شرطی‌سازی، لیست‌ها و کلیدها، مدیریت state، هوک‌ها، پرفورمنس و الگوهای پیشرفته) را پوشش می‌دهد.


۱) JSX چیست و چرا؟

  • خوانایی بالا و نزدیکی به ساختار UI
  • اسکوپ و منطق جاوااسکریپت در کنار View
  • بهینه‌سازی هوشمند توسط React و ابزارهای ساخت

قواعد JSX

  • کامپوننت‌ها باید یک ریشه داشته باشند (از <div> یا <React.Fragment> استفاده کنید).
  • به‌جای class از className استفاده کنید.
  • استایل inline به‌صورت آبجکت جاوااسکریپت است (camelCase).
  • عبارت‌های JS را داخل {} قرار دهید.
// یک کامپوننت ساده
function Hello() {
const name = "Piero";
return (
&amp;lt;div className="box"&amp;gt;
&amp;lt;h2&amp;gt;سلام، {name}!&amp;lt;/h2&amp;gt;
&amp;lt;/div&amp;gt;
);
}

۲) درج متغیرها و عبارات در JSX

هر عبارت جاوااسکریپت را می‌توانید با آکولاد در JSX بنویسید.

const price = 129_000;
const user = { firstName: "Sara", lastName: "Karimi" };

export default function Card() {
return (
&amp;lt;section&amp;gt;

مبلغ: {price.toLocaleString("fa-IR")}

نام: {${user.firstName} ${user.lastName}}
{price &amp;gt; 100000 ? &amp;lt;strong&amp;gt;پیشنهاد ویژه!&amp;lt;/strong&amp;gt; : null}
&amp;lt;/section&amp;gt;
);
}

۳) شرطی‌سازی در JSX

از عملگر سه‌تایی، AND منطقی یا جداسازی منطق قبل از return استفاده کنید.

// 1) سه‌تایی
{isLoading ? &amp;lt;Spinner /&amp;gt; : &amp;lt;DataList /&amp;gt;}

// 2) AND منطقی (برای نمایش شرطی کوتاه)
{error &amp;amp;&amp;amp; 
خطا: {error.message}
}

// 3) جداسازی منطق
let content;
if (isLoading) content = &amp;lt;Spinner /&amp;gt;;
else if (error) content = &amp;lt;ErrorView /&amp;gt;;
else content = &amp;lt;DataList /&amp;gt;;
return &amp;lt;div&amp;gt;{content}&amp;lt;/div&amp;gt;;

۴) رندر لیست‌ها و کلیدها (keys)

برای عملکرد و جلوگیری از باگ در Diff، به هر آیتم یک key یکتا بدهید (از id پایدار استفاده کنید).

const items = [
{ id: "a1", title: "React" },
{ id: "b2", title: "JSX" },
{ id: "c3", title: "Hooks" },
];

function List() {
return (
&amp;lt;ul&amp;gt;
{items.map(item =&amp;gt; (
&amp;lt;li key={item.id}&amp;gt;{item.title}&amp;lt;/li&amp;gt;
))}
&amp;lt;/ul&amp;gt;
);
}

۵) پراپس‌ها، State و رویدادها

پراپس‌ها

function Button({ children, onClick, type = "button" }) { return &amp;lt;button type={type} onClick={onClick}&amp;gt;{children}&amp;lt;/button&amp;gt;; }

// استفاده
&amp;lt;Button onClick={() =&amp;gt; alert("clicked!")}&amp;gt;کلیک&amp;lt;/Button&amp;gt;

State و رویدادها با Hooks

import { useState } from "react";

function Counter() {
const [count, setCount] = useState(0);
return (
&amp;lt;div&amp;gt;

شمارنده: {count}
&amp;lt;button onClick={() =&amp;gt; setCount((c) =&amp;gt; c + 1)}&amp;gt;افزایش&amp;lt;/button&amp;gt;
&amp;lt;/div&amp;gt;
);
}

کنترل فرم (Controlled Components)

import { useState } from "react";

function LoginForm() {
const [email, setEmail] = useState("");

const submit = (e) =&amp;gt; {
e.preventDefault();
console.log({ email });
};

return (
&amp;lt;form onSubmit={submit}&amp;gt;
&amp;lt;input
value={email}
onChange={(e) =&amp;gt; setEmail(e.target.value)}
placeholder="ایمیل"
/&amp;gt;
&amp;lt;button&amp;gt;ارسال&amp;lt;/button&amp;gt;
&amp;lt;/form&amp;gt;
);
}

۶) Fragment، Portal و Context

Fragment

return ( &amp;lt;&amp;gt; &amp;lt;Header /&amp;gt; &amp;lt;Main /&amp;gt; &amp;lt;/&amp;gt; );

Portal (رندر خارج از سلسله‌مراتب معمول)

import { createPortal } from "react-dom";

function Modal({ children }) {
return createPortal(
&amp;lt;div className="backdrop"&amp;gt;{children}&amp;lt;/div&amp;gt;,
document.getElementById("modal-root")
);
}

Context (مدیریت وضعیت سراسری سبک)

import { createContext, useContext } from "react";

const ThemeContext = createContext("light");

function App() {
return (
&amp;lt;ThemeContext.Provider value="dark"&amp;gt;
&amp;lt;Toolbar /&amp;gt;
&amp;lt;/ThemeContext.Provider&amp;gt;
);
}

function Toolbar() {
const theme = useContext(ThemeContext);
return &amp;lt;div data-theme={theme}&amp;gt;Toolbar&amp;lt;/div&amp;gt;;
}

۷) الگوهای حرفه‌ای با Hooks

بهینه‌سازی پرفورمنس: memo, useMemo, useCallback

import React, { useMemo, useCallback } from "react";

const Expensive = React.memo(function Expensive({ value }) {
console.log("render");
return &amp;lt;div&amp;gt;محاسبه: {value}&amp;lt;/div&amp;gt;;
});

function Dashboard({ items }) {
const total = useMemo(() =&amp;gt; items.reduce((s, x) =&amp;gt; s + x, 0), [items]);
const handleClick = useCallback(() =&amp;gt; console.log("clicked"), []);
return (
&amp;lt;div&amp;gt;

جمع: {total}
&amp;lt;button onClick={handleClick}&amp;gt;لاگ&amp;lt;/button&amp;gt;
&amp;lt;Expensive value={total} /&amp;gt;
&amp;lt;/div&amp;gt;
);
}

کداسپلیتینگ با lazy و Suspense

import React from "react";

const Chart = React.lazy(() =&amp;gt; import("./Chart"));

function Reports() {
return (
&amp;lt;React.Suspense fallback={&amp;lt;div&amp;gt;در حال بارگذاری...&amp;lt;/div&amp;gt;}&amp;gt;
&amp;lt;Chart /&amp;gt;
&amp;lt;/React.Suspense&amp;gt;
);
}

Error Boundary

import React from "react";

class ErrorBoundary extends React.Component {
state = { hasError: false };
static getDerivedStateFromError() { return { hasError: true }; }
componentDidCatch(err, info) { console.error(err, info); }
render() {
return this.state.hasError ? &amp;lt;h3&amp;gt;خطایی رخ داد&amp;lt;/h3&amp;gt; : this.props.children;
}
}

export default ErrorBoundary;

۸) الگوی «بالابردن State» و ترکیب‌پذیری

import { useState } from "react";

function Parent() {
const [value, setValue] = useState("");
return (
&amp;lt;&amp;gt;
&amp;lt;Input value={value} onChange={setValue} /&amp;gt;
&amp;lt;Preview value={value} /&amp;gt;
&amp;lt;/&amp;gt;
);
}

function Input({ value, onChange }) {
return &amp;lt;input value={value} onChange={(e) =&amp;gt; onChange(e.target.value)} /&amp;gt;;
}

function Preview({ value }) {
return 
پیش‌نمایش: {value}
;
}

۹) استایل‌دهی در JSX

گزینه‌ها: CSS Module، Styled Components، Tailwind، یا استایل inline.

// استایل inline

&amp;lt;div style={{ padding: 12, borderRadius: 8 }} /&amp;gt;

// CSS Module
import styles from "./box.module.css";

&amp;lt;div className={styles.box}&amp;gt;Box&amp;lt;/div&amp;gt;

۱۰) دسترسی‌پذیری (a11y) و SEO فرانت‌اند

  • استفاده از تگ‌های معنایی (<main>, <nav>, <header>)
  • مشخص‌کردن alt برای تصاویر
  • مدیریت فوکوس و نسبت کنتراست مناسب

۱۱) تست کامپوننت‌ها

// React Testing Library import { render, screen } from "@testing-library/react"; import Button from "./Button";

test("renders label", () =&amp;gt; {
render(&amp;lt;Button&amp;gt;سلام&amp;lt;/Button&amp;gt;);
expect(screen.getByText("سلام")).toBeInTheDocument();
});

۱۲) نمونهٔ اپ کوچک: فهرست کارها (Todo)

import { useState } from "react";

export default function TodoApp() {
const [items, setItems] = useState([]);
const [text, setText] = useState("");

const add = () =&amp;gt; {
if (!text.trim()) return;
setItems((prev) =&amp;gt; [...prev, { id: crypto.randomUUID(), text }]);
setText("");
};

const remove = (id) =&amp;gt; setItems((prev) =&amp;gt; prev.filter(i =&amp;gt; i.id !== id));

return (
&amp;lt;div className="todo"&amp;gt;
&amp;lt;h2&amp;gt;کارها&amp;lt;/h2&amp;gt;
&amp;lt;input value={text} onChange={(e) =&amp;gt; setText(e.target.value)} /&amp;gt;
&amp;lt;button onClick={add}&amp;gt;افزودن&amp;lt;/button&amp;gt;
&amp;lt;ul&amp;gt;
{items.map(i =&amp;gt; (
&amp;lt;li key={i.id}&amp;gt;
{i.text}
&amp;lt;button onClick={() =&amp;gt; remove(i.id)}&amp;gt;حذف&amp;lt;/button&amp;gt;
&amp;lt;/li&amp;gt;
))}
&amp;lt;/ul&amp;gt;
&amp;lt;/div&amp;gt;
);
}

۱۳) نکات حرفه‌ای برای پروژه‌های واقعی

  • ساختار پوشه‌ها بر اساس دامنه (Feature-Sliced) به‌جای تفکیک فایل‌محور.
  • TypeScript برای خودمستندسازی و ایمنی تایپی.
  • ESLint + Prettier برای یکپارچگی کد.
  • استفاده از React Query / SWR برای مدیریت سرور استیت.
  • Next.js برای SSR/SSG، بهبود SEO و رندر سمت سرور.

پرسش‌های متداول (FAQ)

تفاوت JSX و HTML؟ JSX یک سینتکس داخل جاوااسکریپت است؛ برخی ویژگی‌ها متفاوت‌اند (مثل className، onClick).
آیا بدون Babel می‌توان JSX نوشت؟ نه، JSX باید به جاوااسکریپت کامپایل شود (Vite/Next.js/CRA قدیمی).
راه بهینه‌سازی سرعت رندر چیست؟ کلیدهای پایدار، memo/useMemo/useCallback، تقسیم کد با lazy/Suspense و جلوگیری از رندرهای غیرضروری.