useViewParams

نمای یک صفحه (بازه، تب، فیلترها، مرتب‌سازی، چیدمان) در نشانی صفحه — تنها راه DS؛ پیوند و «برگشت» همان نما را باز می‌کنند

معرفی

هوک useViewParams نمای یک صفحهٔ فهرست، داشبورد یا جزئیات را در نشانی صفحه نگه می‌دارد: پیوندی که کسی برایتان می‌فرستد همان بازه، همان تب و همان فیلترها را باز می‌کند، «برگشت» مرورگر نمای قبلی را برمی‌گرداند، و دکمهٔ «کپی پیوند این نما» یک خط است.

تا 7.8 DS نوشتن نشانی را از صفحه ممنوع کرده بود («فیلتر هرگز در URL نه»). دلیلش درست بود: سه اجرای X5 سه جور پارامتر نوشتند (نام، آرایه، تاریخ، push یا replace، خواندن در اولین رندر). ولی «نه» پاسخ نیاز واقعی نیست — چهار سند طراحی مستقل پیوند عمیق و نمای قابل‌اشتراک را خواستند — و دلیل ممنوعیت («چند راه») با ساختن یک راهِ DS از بین می‌رود. پس قاعده برنگشت، کامل شد: به‌جای «هرگز URL»، «URL فقط با useViewParams». هر چیزی که پیش‌تر ممنوع بود (useSearchParams، useFilterParams/FilterProvider، history.replaceState در فایلی که ListPage یا DashboardPage دارد) همچنان گزارش می‌شود؛ useViewParams و useUrlQuery مجازند.

چه زمانی استفاده کنیم

  • بازه، تب، فیلترها، مرتب‌سازی یا چیدمانِ (کارت/جدول) یک صفحه که باید با پیوند به اشتراک گذاشته شود یا پس از «برگشت» بماند
  • دکمهٔ «کپی پیوند» روی یک صفحهٔ تحلیلی

چه زمانی استفاده نکنیم

  • متنی که کاربر هنوز در حال تایپ آن است: state جزء. جست‌وجوی ارسال‌شده useUrlQuery است
  • انتخاب ردیف‌ها، حالت باز یک منو، جای یک فید با مکان‌نما: state جزء
  • جزئیات باز یک ردیف در شیت: useQueryParamSheet؛ کشوی موجودیت: useEntityDrawer
  • داده‌ای که اندازهٔ یک درخواست دارد (شمارهٔ صفحهٔ cursor، شناسهٔ نتیجه): state جزء

استفاده

import { arrayParam, enumParam, periodParam, useViewParams } from '@partodata/ui/templates'

// یک بار، در سطح ماژول: طرح صفحه است، state نیست
const VIEW = {
  range: periodParam('30d'), // 7d · 30d · 90d · all · 2026-09-01_2026-09-30 (ASCII؛ جلالی فقط در نمایش)
  tab: enumParam(['overview', 'posts'] as const, 'overview'),
  level: arrayParam<'urgent' | 'high' | 'medium' | 'low'>([]),
  view: enumParam(['cards', 'table'] as const, 'cards'),
}

function Issues() {
  const [view, setView, { href, reset }] = useViewParams(VIEW)
  return (
    <ListPage
      title="مسائل رصدشده"
      filtered={view.level.length > 0}
      onClearFilters={() => reset(['level'])}
      secondaryActions={<CopyButton value={href({}, { absolute: true })} label="کپی پیوند این نما" />}
      /* … */
    />
  )
}
setView({ level: ['urgent'] }) // یک ورودی تاریخچه جایگزین می‌شود: ?level=urgent
setView({ tab: 'posts' }, { history: 'push' }) // تب: «برگشت» به تب قبلی برمی‌گردد
setView((current) => ({ page: current.tab === 'posts' ? 1 : current.page })) // از نشانیِ همین لحظه
  • اولین رندر از نشانی خوانده می‌شود (سرور و رندر hydration مقدار پیش‌فرض می‌گویند، و بلافاصله نشانی می‌رسد).
  • مقداری که با پیش‌فرض برابر باشد از نشانی حذف می‌شود: نشانی ساده همان نمای پیش‌فرض است.
  • ارقام فارسی و عربی‌هندی نشانی به ASCII خوانده می‌شوند؛ مقدار ناخوانا همان پیش‌فرض است.
  • فقط پارامترهای طرح نوشته می‌شوند؛ دیگران (q، شناسهٔ کشو) دست‌نخورده می‌مانند.
  • بدون history: 'push' ورودی تاریخچه جایگزین می‌شود، تا «برگشت» برای رفتن بین صفحه‌ها مفید بماند نه برای هر دست‌کاری فیلتر.

سازنده‌های پارامتر

سازندهمقدارنوشته می‌شود
enumParam(values, default)یکی از مقدارهای بسته (تب، مرتب‌سازی، چیدمان)tab=posts
periodParam(default)7d، 30d، all یا بازهٔ دقیق میلادیrange=2026-09-01_2026-09-30
arrayParam(default, { allowed })فهرست مقدارها؛ مقدار ناشناخته افتاده می‌شودlevel=urgent,high
stringParam(default, { maxLength })متن کوتاهname=…
numberParam(default, { min, max, integer })عددpage=3
booleanParam(default)سوئیچmine=1

پارامترها

پارامترنوعتوضیح
schemaViewSchemaنام پارامتر نشانی ← سازنده
optionsUseViewParamsOptionsتنظیمات اختیاری

UseViewParamsOptions

Prop

Type

مقدار بازگشتی

[view, setView, { href, reset }]

Prop

Type

نکتهٔ روتر

هوک فقط با History API کار می‌کند، پس با Next.js App Router (که pushState و replaceState را می‌پذیرد)، react-router و صفحهٔ ساده کار می‌کند و روتر چیزی نمی‌خواهد. useLocation() روتر در تغییرِ نشانی به‌روز می‌شود؛ خود هوک با رویداد خودش و popstate هماهنگ است.


هوک‌های مرتبط

  • جست‌وجوی ارسال‌شده در URL → useUrlQuery از @partodata/ui/templates
  • جزئیات باز یک ردیف → useQueryParamSheet
  • وضعیت یک FilterProvider در CustomPage → useFilterParams