راهنمای نصب Skill
فایل SKILL.md را دانلود کنید و در مسیر مخصوص ایجنت موردنظرتان قرار دهید. پیشنهاد میکنیم پیش از فعالسازی، محتوای کامل فایل و سطح دسترسی آن را بررسی کنید.
Codex
~/.codex/skills/state-boundary-architecture-review/SKILL.mdClaude Code
.claude/skills/state-boundary-architecture-review/SKILL.mdCursor
.cursor/skills/state-boundary-architecture-review/SKILL.mdGitHub Copilot
.github/skills/state-boundary-architecture-review/SKILL.md</>مشاهده محتوای خام SKILL.mdفقط دستورالعملهایی را ببینید که ایجنت برنامهنویسی دریافت میکند؛ بدون عنوان، تگ و متادیتای کاتالوگ.
---
name: "state-boundary-architecture-review"
description: "State پروژه React را به local، server، URL و global client state تفکیک کن، source of truth را مشخص کن و state تکراری یا ownership اشتباه را بدون ساخت store اضافی اصلاح کن."
---
# بازبینی معماری State در React
این Skill را وقتی اجرا کن که state در چند Store، Hook، Query Cache، URL یا Component تکرار شده، sync effect زیاد شده یا مشخص نیست source of truth یک داده کجاست.
هدف انتخاب یک state library نیست. ابتدا **نوع و مالکیت state** را مشخص کن و سپس کوچکترین ابزار مناسب را نگه دار.
## طبقهبندی State
```text
Local UI state → نزدیکترین Component مالک
Server state → cache/data layer
URL state → router/search params
Global client state → فقط state واقعاً سراسری مرورگر
Derived state → محاسبه شود، ذخیره نشود
```
این دستهها قانون مطلق نیستند؛ ownership را از lifecycle و source of truth تعیین کن.
## Workflow
### 1. State Inventory بساز
```text
State:
Source of truth:
Readers:
Writers:
Lifetime:
Must survive navigation?
Must be shareable in URL?
Comes from server?
```
### 2. Duplicate Source of Truth را پیدا کن
Smellهای مهم: response Query در Zustand/Redux کپی میشود؛ search param هم در URL و هم در `useState` نگه داشته میشود؛ مقدار derived با Effect دوباره set میشود؛ parent و child هر دو نسخه قابلویرایش یک state را نگه میدارند؛ persistence بدون نیاز محصول فعال شده است.
### 3. Server State را از Client State جدا کن
دادهای که authoritative source آن API است معمولاً باید در server-state layer باقی بماند.
```text
API
↓
Query cache
↓
UI
```
Modal open، selected tab محلی یا draft موقت فرم را فقط به دلیل اینکه چند Component دارند در Query Cache قرار نده.
### 4. URL را برای State قابلاشتراک جدی بگیر
Filter، sort، page و tabی که باید با refresh، back/forward یا share link حفظ شود candidate خوبی برای URL است. از mirror کردن آن در state محلی خودداری کن مگر یک draft موقت قبل از apply لازم باشد.
### 5. Derived State را ذخیره نکن
```tsx
// avoid
const [fullName, setFullName] = useState("")
useEffect(() => {
setFullName(`${firstName} ${lastName}`)
}, [firstName, lastName])
// prefer
const fullName = `${firstName} ${lastName}`
```
### 6. Global Store را آخر انتخاب کن
قبل از انتقال state به Store بپرس آیا میتواند local بماند، server state است، URL مالک بهتری است یا Context محدود به subtree کافی است.
### 7. Refactor را با حذف Sync شروع کن
هر `useEffect` که فقط دو state را با هم sync میکند بررسی کن. اغلب حذف state تکراری از ساخت selector یا middleware جدید مؤثرتر است.
## خروجی مورد انتظار
```text
State:
Current owner:
Problem:
Recommended owner:
Migration:
Risk:
Validation:
```
معماری جدید را فقط برای یکدستکردن نام ابزارها تحمیل نکن. هدف کاهش source of truth، sync دستی و coupling است.
پس از refactor، refresh، navigation، back/forward، loading/error، optimistic mutation و تستهای موجود را در محدوده مرتبط بررسی کن.
این Skill را وقتی اجرا کن که state در چند Store، Hook، Query Cache، URL یا Component تکرار شده، sync effect زیاد شده یا مشخص نیست source of truth یک داده کجاست.
هدف انتخاب یک state library نیست. ابتدا نوع و مالکیت state را مشخص کن و سپس کوچکترین ابزار مناسب را نگه دار.
طبقهبندی State
Local UI state → نزدیکترین Component مالک
Server state → cache/data layer
URL state → router/search params
Global client state → فقط state واقعاً سراسری مرورگر
Derived state → محاسبه شود، ذخیره نشود
این دستهها قانون مطلق نیستند؛ ownership را از lifecycle و source of truth تعیین کن.
Workflow
1. State Inventory بساز
State:
Source of truth:
Readers:
Writers:
Lifetime:
Must survive navigation?
Must be shareable in URL?
Comes from server?
2. Duplicate Source of Truth را پیدا کن
Smellهای مهم: response Query در Zustand/Redux کپی میشود؛ search param هم در URL و هم در useState نگه داشته میشود؛ مقدار derived با Effect دوباره set میشود؛ parent و child هر دو نسخه قابلویرایش یک state را نگه میدارند؛ persistence بدون نیاز محصول فعال شده است.
3. Server State را از Client State جدا کن
دادهای که authoritative source آن API است معمولاً باید در server-state layer باقی بماند.
API
↓
Query cache
↓
UI
Modal open، selected tab محلی یا draft موقت فرم را فقط به دلیل اینکه چند Component دارند در Query Cache قرار نده.
4. URL را برای State قابلاشتراک جدی بگیر
Filter، sort، page و tabی که باید با refresh، back/forward یا share link حفظ شود candidate خوبی برای URL است. از mirror کردن آن در state محلی خودداری کن مگر یک draft موقت قبل از apply لازم باشد.
5. Derived State را ذخیره نکن
// avoid
const [fullName, setFullName] = useState("")
useEffect(() => {
setFullName(`${firstName} ${lastName}`)
}, [firstName, lastName])
// prefer
const fullName = `${firstName} ${lastName}`
6. Global Store را آخر انتخاب کن
قبل از انتقال state به Store بپرس آیا میتواند local بماند، server state است، URL مالک بهتری است یا Context محدود به subtree کافی است.
7. Refactor را با حذف Sync شروع کن
هر useEffect که فقط دو state را با هم sync میکند بررسی کن. اغلب حذف state تکراری از ساخت selector یا middleware جدید مؤثرتر است.
خروجی مورد انتظار
State:
Current owner:
Problem:
Recommended owner:
Migration:
Risk:
Validation:
معماری جدید را فقط برای یکدستکردن نام ابزارها تحمیل نکن. هدف کاهش source of truth، sync دستی و coupling است.
پس از refactor، refresh، navigation، back/forward، loading/error، optimistic mutation و تستهای موجود را در محدوده مرتبط بررسی کن.