useLocalStorage

همگام‌سازی state با localStorage — با سریالیزاسیون JSON و مقاوم در برابر SSR

معرفی

هوک useLocalStorage مشابه useState عمل می‌کند، اما مقدار را در localStorage ذخیره می‌کند تا بین refresh صفحه و session ها باقی بماند.

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

  • ذخیره ترجیحات کاربر (مثلاً حالت نمایش grid/list)
  • نگهداری وضعیت فیلترهای جدول بین بازدیدها
  • ذخیره draft فرم‌ها

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

  • برای داده‌های حساس (رمز عبور، توکن) — از httpOnly cookie استفاده کنید
  • برای داده‌های حجیم — localStorage محدودیت ~5MB دارد
  • برای state مشترک بین tab ها — از BroadcastChannel یا storage event استفاده کنید

استفاده

import { useLocalStorage } from '@partodata/ui'
import { EntityLayoutToggle } from '@partodata/ui/social'

function SettingsPanel() {
  const [viewMode, setViewMode] = useLocalStorage<'card' | 'row'>('view-mode', 'card')

  return <EntityLayoutToggle layouts={['card', 'row']} value={viewMode} onValueChange={setViewMode} />
}

الگوی رایج: ذخیرهٔ نمای فهرست

ترجیح کاربر (مثل نمای شبکه یا فهرست) بعد از بارگذاری دوباره می‌ماند؛ جست‌وجو، فیلترها و شمارهٔ صفحهٔ یک ListPage وضعیت خود کامپوننت‌اند (React.useState) و ذخیره نمی‌شوند:

function InfluencersPage() {
  const [view, setView] = useLocalStorage<'tile' | 'row'>('influencers-view', 'row')
  const rows = data?.items ?? []

  return (
    <ListPage
      title="اینفلوئنسرها"
      toolbarEnd={<EntityLayoutToggle layouts={['tile', 'row']} value={view} onValueChange={setView} />}
      skeleton={view === 'tile' ? 'cards' : 'table'}
      state={pageState({
        data: data?.items,
        isLoading,
        error,
        onRetry: load,
        emptyCopy: { title: 'هنوز اینفلوئنسری ثبت نشده است' },
      })}
    >
      {view === 'tile' ? (
        <div className="grid grid-cols-[repeat(auto-fill,minmax(min(var(--layout-tile-min-width),100%),1fr))] gap-layout-block-gap">
          {rows.map((row) => (
            <Account key={row.id} account={row} layout="card" />
          ))}
        </div>
      ) : (
        <DataTable columns={columns} data={rows} />
      )}
    </ListPage>
  )
}

پارامترها

پارامترنوعتوضیح
keystringکلید localStorage
initialValueTمقدار پیش‌فرض اگر کلید وجود نداشته باشد

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

نوعتوضیح
[T, (value: T | ((prev: T) => T)) => void]مشابه useState — مقدار فعلی و تابع setter

جزئیات فنی

  • SSR-safe: در سرور مقدار initialValue برمی‌گرداند
  • سریالیزاسیون: از JSON.stringify/parse استفاده می‌کند
  • خطاپذیر: اگر localStorage پر باشد یا مرورگر در حالت خصوصی باشد، بدون خطا ادامه می‌دهد
  • Setter تابعی: مانند useState، می‌توانید تابع updater ارسال کنید

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

  • برای debounce کردن مقدار قبل از ذخیره → useDebounce