سوالات مصاحبه React در سال ۱۴۰۵ | راهنمای کامل استخدام

سوالات مصاحبه React در سال ۱۴۰۵ | راهنمای کامل استخدام
مصاحبههای ریاکت در چند سال اخیر به شکل چشمگیری تغییر کردن.
چند سال پیش، از داوطلبها درباره کامپوننتهای کلاسی، متدهای چرخه حیات و اینکه آیا میتونن تفاوت بین componentDidMount() و componentDidUpdate() رو توضیح بدن سؤال میشد.
امروزه، این سؤالها بهندرت اهمیت دارن.
مصاحبههای مدرن ریاکت روی مجموعه کاملاً متفاوتی از موضوعات تمرکز دارن:
- رفتار رندر (Rendering behavior)
- مدیریت وضعیت (State management)
- قابلیتهای ریاکت ورژن ۱۹
- کامپوننتهای سرور (Server Components)
- بهینهسازی عملکرد (Performance optimization)
- تصمیمهای معماری (Architecture decisions)
- تجربه توسعهدهنده (Developer experience)
مصاحبهگرها میخوان بفهمن آیا توسعهدهنده میتونه اپلیکیشنهای بزرگ ریاکت رو بسازه و نگهداری کنه — نه اینکه مستندات API رو حفظ کرده یا نه.
این راهنما سؤالهایی از ریاکت رو پوشش میده که بیشتر در مصاحبههای مدرن دیده میشن و منطق پشت پاسخها رو توضیح میده.
درک اینکه ریاکت (React) واقعاً چطور رندر میکنه
خیلی از توسعهدهندگان React میتونن اپلیکیشن بسازن بدون اینکه کاملاً بدونن بعد از تغییر state دقیقاً چه اتفاقی میوفته.
متأسفانه این موضوع در مصاحبهها خیلی زود مشخص میشه.
React چیه؟
سادهترین پاسخ اینه :
ریاکت یک کتابخانه جاوااسکریپت برای ساخت رابطهای کاربری با استفاده از کامپوننتهای قابل استفادهٔ مجدد هست.
اما این پاسخ بهتر توضیح میده چرا توسعهدهندهها ریاکت رو انتخاب میکنن:
ریاکت به توسعهدهندگان اجازه میده رابط کاربری (UI) رو بهصورت declarative توصیف کنن. بهجای اینکه DOM رو بهصورت دستی بروزرسانی کنیم، کامپوننتها فقط مشخص میکنن رابط کاربری (UI) در یک state مشخص چگونه باید باشه و ریاکت خودش بروزرسانیها رو مدیریت میکنه.
JSX چیه؟
JSX یک گسترش سینتکس (syntax extension) هست که اجازه میده داخل جاوااسکریپت از سینتکسی شبیه HTML استفاده کنیم.
مثال:
function WelcomeCard() {
return (
<section>
<h2>Welcome</h2>
<p>Thanks for joining.</p>
</section>
);
}
در زمان کامپایل، JSX به فراخوانیهای ایجاد React element تبدیل میشه.
در پروژههای مدرن ریاکت معمولاً لازم نیست توسعهدهندهها به این تبدیل فکر کنن، اما مصاحبهگرها هنوز گاهی دربارهاش سؤال میپرسن.
Virtual DOM چیه؟
یکی از رایجترین سؤالهای مصاحبه ریاکت.
Virtual DOM یک نمایش در حافظه (in-memory representation) از UI است.
وقتی state تغییر میکنه:
- ریاکت یک درخت مجازی جدید ایجاد میکنه
- اونو با درخت قبلی مقایسه میکنه
- حداقل تغییرات لازم رو محاسبه میکنه
- DOM مرورگر رو بهصورت بهینه بروزرسانی میکنه
بسیاری از داوطلبها اشتباه میگن Virtual DOM «از DOM سریعتر هست».
این کاملاً درست نیست.
مزیت واقعی این است که ریاکت عملیاتهای پرهزینه روی DOM رو به حداقل میرسونه.
بازآشتی یا همگامسازی (Reconciliation) چیست؟
Reconciliation فرآیندی هست که ریاکت برای مقایسه دو درخت مجازی استفاده میکنه.
مثلاً:
function Counter({ count }: Props) {
return <span>{count}</span>;
}
اگر مقدار count از ۵ به ۶ تغییر کنه، ریاکت کل درخت کامپوننت رو از اول نمیسازه.
بلکه کوچکترین تغییر ممکن رو پیدا میکنه و فقط همان نود رو بروزرسانی میکنه.
Keys: سؤالی که همهجا دیده میشه
چرا Keys مهم هست؟
Keys به ریاکت کمک میکنند عناصر را بین رندرها شناسایی کند.
بد:
{
users.map((user, index) => (
<UserRow
key={index}
user={user}
/>
));
}
خوب:
{
users.map((user) => (
<UserRow
key={user.id}
user={user}
/>
));
}
استفاده از index آرایه میتونه باعث این مشکلات بشه:
- حفظ نادرست state
- خراب شدن انیمیشنها
- رفتار غیرمنتظره در فرمها
- رندرهای غیرضروری
این سؤال به طور عجیبی زیاد در مصاحبهها مطرح میشه.
سؤالهای مدرن درباره هوکها (Hooks)
هوکها هنوز یکی از مهمترین موضوعات مصاحبه هستن.
چه زمانی باید از useState استفاده کرد؟
وقتی دادهای روی رندر UI تأثیر میگذارد.
const [isOpen, setIsOpen] =
useState(false);
مثالها:
- مودالها (modals)
- ورودیهای فرم
- تب انتخابشده
- toggleهای UI
اگر تغییر یک مقدار باید باعث بروزرسانی رابط کاربری (UI) بشه، اون مقدار باید در state باشه.
چه زمانی باید بهجای useState از useRef استفاده کرد؟
یک سؤال رایج در سطح senior.
هر مقداری لازم نیست در state باشه.
بد:
const [socket, setSocket] =
useState<WebSocket | null>(
null
);
بهتر:
const socketRef =
useRef<WebSocket | null>(
null
);
موارد مناسب برای ref:
- نمونههای WebSocket
- تایمرها
- عناصر DOM
- کتابخانههای خارجی
Refها باعث رندرمجدد (re-render) نمیشوند.
بزرگترین اشتباه در useEffect چیه؟
خیلی از توسعهدهندگان از effect برای derived state استفاده میکنن.
مثال:
const [fullName, setFullName] =
useState('');
useEffect(() => {
setFullName(
`${firstName} ${lastName}`
);
}, [firstName, lastName]);
این کار غیرضروری هست.
بهتر:
const fullName =
`${firstName} ${lastName}`;
اگر مقداری رو میشه در زمان رندر محاسبه کرد، معمولاً باید همونجا محاسبه بشه.
useEffect در مقابل useLayoutEffect
یک سؤال کلاسیک مصاحبه.
useEffect بعد از paint اجرا میشه.useLayoutEffect قبل از paint اجرا میشه.
مثال:
useLayoutEffect(() => {
const width =
element.current?.offsetWidth;
}, []);
وقتی لازم هست قبل از paint مرورگر با DOM اندازهگیری یا همگامسازی انجام بدید، از useLayoutEffect استفاده کنید.
برای بیشتر side effectها، useEffect مناسب هست.
سؤالهای ریاکت ورژن ۱۹
بخش بزرگی از مصاحبههای مدرن روی این قسمت تمرکز دارن.
Actions چیست؟
Actions مدیریت state ناهمگام رو سادهتر میکنن.
قبل از ریاکت ورژن ۱۹:
const [loading, setLoading] =
useState(false);
const handleSubmit =
async () => {
setLoading(true);
try {
await saveProfile();
} finally {
setLoading(false);
}
};
ریاکت ورژن ۱۹:
const [
profile,
submitProfile,
pending,
] = useActionState(
updateProfile,
null
);
کدهای قالب و تکراری کمتر
UX بهتر
stateهای pending داخلی
useOptimistic چیه؟
یکی از محبوبترین سؤالهای ریاکت ۱۹.
این هوک اجازه میده قبل از تمام شدن درخواست سرور، رابط کاربری (UI) بهصورت خوشبینانه (optimistic) بروزرسانی بشه.
const [
messages,
addOptimisticMessage,
] = useOptimistic(
chatMessages,
(current, text) => [
...current,
{
id: crypto.randomUUID(),
text,
pending: true,
},
]
);
UI بلافاصله بروزرسانی میشه.
پاسخ سرور بعداً میرسه.
کاربر احساس میکنه اپلیکیشن خیلی سریعتر هست.
یونس قربانی : اگر دوره ریاکت منو دیده باشی شاید یادت باشه که اینکارو به صورت دستی انجام میدادیم.
کامپایلر ریاکت (React Compiler) چیه ؟
کامپایلر ریاکت یکی از بزرگترین تغییرات ریاکت در سالهای اخیر هست.
قبلاً:
const activeUsers =
useMemo(
() =>
users.filter(
(user) => user.active
),
[users]
);با کامپایلر ریاکت:
const activeUsers =
users.filter(
(user) => user.active
);
کامپایلر میتونه در جاهایی که امن هست memoization رو بهصورت خودکار اضافه کنه.
با گسترش استفاده ازش، خیلی از الگوهای بهینهسازی دستی ممکنه از بین برن.
تفاوت کامپوننتهای سرور و کامپوننتهای کلاینت چیه؟
کامپوننتهای سرور (Server Components)
- روی سرور اجرا میشن
- جاوااسکریپت به مرورگر ارسال نمیکنن
- میتونن مستقیماً به دیتابیس دسترسی داشته باشن
- نمیتونن از هوکها استفاده کنن
کامپوننتهای کلاینت (Client Components)
- در مرورگر اجرا میشن
- تعاملپذیری دارن
- state و effect دارن
- تعامل کاربر رو مدیریت میکنن
یک توسعهدهنده قوی ریاکت ۱۹ باید بدونه هر کدوم کجا استفاده میشن.
سؤالهای مربوط به Performance
سؤالهای performance اغلب تفاوت بین junior و senior رو مشخص میکنن.
چه چیزی باعث رندر مجدد (re-render) غیرضروری میشه؟
یک مثال رایج:
<Dashboard
onRefresh={() =>
fetchAnalytics()
}
/>
در هر رندر یک تابع جدید ساخته میشه.
بهتر:
const handleRefresh =
useCallback(() => {
fetchAnalytics();
}, []);
<Dashboard
onRefresh={
handleRefresh
}
/>
اگرچه کامپایلر ریاکت نیاز به memoization دستی رو کمتر میکنه، اما درک رفتار رندر همچنان مهم هست.
چطور یک جدول بزرگ رو بهینه میکنی؟
یک سؤال رایج در پروژههای سازمانی.
جواب باید شامل این موارد باشه:
- Virtualization
- Pagination
- ستونهای memoized
- فیلتر سمت سرور
- کلیدهای پایدار
مثال:
import {
FixedSizeList,
} from 'react-window';
Virtualization معمولاً بیشترین بهبود عملکرد رو ایجاد میکنه.
Context در مقابل Zustand
این سؤال در مصاحبهها بیشتر دیده میشه.
از Context استفاده کنید برای:
- Theme
- Authentication
- Localization
- Feature flags
از Zustand استفاده کنید برای:
- state داشبورد
- فیلترهای جدول
- نتایج جستجو
- دادههای نمودار
یک قانون ساده:
Context برای پیکربندی اپلیکیشن هست.
Zustand برای business state هست.
سؤالهای مدیریت State
Prop Drilling چیست؟
Prop drilling زمانی اتفاق میوفته که داده از میان کامپوننتهایی عبور کنه که خودشون ازش استفاده نمیکنن.
<App>
<Layout>
<Sidebar>
<Profile />
</Sidebar>
</Layout>
</App>
اگر داده کاربر از همه این لایهها عبور بکنه، prop drilling رخ میده.
راهحلها:
- Context
- Zustand
- Redux Toolkit
چه زمانی باید از useReducer استفاده کرد؟
یک پاسخ خوب:
وقتی تغییرات state پیچیده میشوند یا چند بخش از state باید همزمان تغییر کنن.
const [state, dispatch] =
useReducer(
reducer,
initialState
);
در بسیاری از موارد این روش از چند useState خواناتر هست.
سؤالهای React Router
چگونه بهصورت برنامهای (programmatically) ناوبری میکنید؟
import {
useNavigate,
} from 'react-router-dom';
function DashboardButton() {
const navigate =
useNavigate();
return (
<button
onClick={() =>
navigate('/dashboard')
}
>
Dashboard
</button>
);
}
چگونه مسیرهای خصوصی را محافظت میکنید؟
function ProtectedRoute({
children,
}: Props) {
return isAuthenticated
? children
: (
<Navigate
to="/login"
/>
);
}
Private routeها هنوز یک موضوع رایج در مصاحبهها هستن.
چگونه query parameterها را میخوانید؟
const [params] =
useSearchParams();
const page =
params.get('page');
سؤال ساده.
اما زیاد پرسیده میشه.
سؤالهای Testing
بسیاری از شرکتها حالا به دانش تست اهمیت میدن.
چرا کتابخانههای تست ریاکتی نسبت به Enzyme ترجیح داده میشود؟
کتابخونههای تست ریاکت توسعهدهندهها رو تشویق میکنه رفتار برنامه رو تست کنن، نه جزئیات پیادهسازی.
تست بد:
wrapper.state();
تست خوب:
screen.getByRole(
'button'
);
تست با اپلیکیشن مثل کاربر واقعی تعامل میکند.
چگونه هوکهای سفارشی را تست میکنید؟
const { result } =
renderHook(() =>
useCounter()
);
این روش الان استاندارد هست.
چه چیزهایی باید تست شوند؟
داوطلبهای خوب روی اینها تمرکز میکنن:
- تعاملات کاربر
- منطق کسبوکار
- دسترسپذیری
- جریانهای حیاتی برنامه
نه جزئیات داخلی پیادهسازی.
سؤالهای معماری در سطح Senior
این سؤالها در مصاحبههای ارشد بیشتر دیده میشن.
چه زمانی React.memo باعث بدتر شدن عملکرد (performance) میشود؟
Memoization هزینه دارد.
اگر یک کامپوننت کوچک و ارزان برای رندر باشد، memoization ممکن است کار بیشتری ایجاد کند تا اینکه صرفهجویی کند.
همیشه قبل از بهینهسازی اندازهگیری کنید.
چه زمانی state باید در React Query باشد نه در Zustand؟
React Query مدیریت میکند:
- server state
- caching
- همگامسازی
- refetch در پسزمینه
Zustand مدیریت میکند:
- client state
- UI state
- state موقتی اپلیکیشن
درک این تفاوت یک نشانه قوی از سطح senior است.
چرا Derived State معمولاً اشتباه است؟
اگر دادهای را بتوان از state موجود محاسبه کرد، ذخیره کردن آن باعث تکرار داده میشود.
بد:
const [fullName, setFullName] =
useState('');
بهتر:
const fullName =
`${firstName} ${lastName}`;
state کمتر یعنی باگ کمتر.
فرق خوب بودن در ریاکت با خوب بودن در جاوااسکریپت چیست؟
سوال خیلی مهمی هست. خیلی از مشکلات ریاکت اصلاً ریاکتی نیستن. جاوااسکریپتی هستن. دقیقاً به همین خاطر یک دوره ساختم : دوره جاوااسکریپت مورد نیاز React و Next.js : فراتر از سینتکس
اگر اینها رو نفهمی، در ریاکت هم به مشکل میخوری:
- closure
- برابری ارجاعی (reference equality)
- رفتار ناهمگام (async behavior)
- تغییرناپذیری (immutability)
- حلقه رویداد (event loop)
- ماژولها (modules)
جواب حرفهای:
ریاکت روی مفاهیم جاوااسکریپت سوار هست. کسی که جاوااسکریپت رو عمیق نفهمه، معمولاً در هوکها، وابستگیها، memoization و باگهای state گیر میکنه.
جمعبندی
مصاحبههای مدرن React دیگر درباره حفظ کردن APIها نیستن.
بهترین داوطلبها این موارد رو درک میکنن:
- رفتار رندر
- هوکها
- مدیریت state
- قابلیتهای ریاکت ورژن ۱۹
- بهینهسازی عملکرد
- کامپوننتهای سرور (Server Components)
- trade-offهای معماری
بهجای حفظ کردن دهها پاسخ جداگانه، روی درک اینکه ریاکت چگونه کار میکند تمرکز کنید.
این دانش خیلی فراتر از هر مصاحبهای کاربرد داره.
سلام بر دوستان عزیز و یاران جان 👋
این سوالات بر اساس بررسی مقالات معتبر خارجی و تحلیل روند مصاحبههای واقعی شرکتهای بینالمللی جمعآوری و ترجمه شدن. با خوندنشون متوجه شدم که واقعاً زنگ تفکیک مصاحبههای React به صدا دراومده 😊 اگر توسعهدهنده React هستی و قصد استخدامی داری، این سوالات دقیقاً همون مواردیه که در مصاحبههای مدرن پرسیده میشن.
به همین دلیل، متن رو با دقت کامل ترجمه و تنظیم کردم تا در اختیار شما عزیزان قرار بدم.

