Skip to content

feat: add use-local-storage-state#62

Open
Debbl wants to merge 3 commits intomainfrom
feat/use-local-storage-state
Open

feat: add use-local-storage-state#62
Debbl wants to merge 3 commits intomainfrom
feat/use-local-storage-state

Conversation

@Debbl
Copy link
Copy Markdown
Owner

@Debbl Debbl commented Feb 27, 2026

Summary by CodeRabbit

  • New Features

    • Introduced a SSR-safe localStorage state hook with cross-tab sync and customizable (de)serialization.
  • Documentation

    • Added comprehensive docs and an interactive demo for the new hook.
    • Added an interactive demo for the hash hook.
  • Tests

    • Added a comprehensive test suite covering initialization, updates, removal, sync, error handling, and SSR scenarios.
  • Chores

    • Registered the new hook in the hooks registry.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Feb 27, 2026

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
shadcn-hooks 27c2f26 Commit Preview URL

Branch Preview URL
Feb 27 2026, 07:43 AM

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Feb 27, 2026

📝 Walkthrough

Walkthrough

Adds a new SSR-safe useLocalStorageState React hook with cross-tab and same-tab synchronization, plus implementation, types, tests, demos, MDX docs, and registry metadata.

Changes

Cohort / File(s) Summary
Hook Implementation & Types
src/registry/hooks/use-local-storage-state/index.ts
New hook implementing SSR-safe localStorage state with caching, optional serializer/deserializer, onError handler, useSyncExternalStore-based subscription, set and remove APIs, and cross-tab synchronization events.
Tests
src/registry/hooks/use-local-storage-state/index.test.ts
Comprehensive test suite validating initialization, persistence, functional updates, removal, same-tab sync, cross-tab storage events, custom serializers, error handling, and SSR behavior.
Demos
src/registry/hooks/use-local-storage-state/demo/demo-01.tsx, src/registry/hooks/use-hash/demo/demo-01.tsx
Adds demo components: one showcasing useLocalStorageState (input, fill, clear) and one showcasing useHash (hash input, presets, clear).
Documentation & References
skills/shadcn-hooks/SKILL.md, skills/shadcn-hooks/references/useLocalStorageState.md, src/registry/hooks/use-local-storage-state/index.mdx, src/registry/hooks/use-hash/index.mdx
Adds skill entry, API reference, MDX guide for useLocalStorageState, and embeds the useHash demo into its MDX page.
Registry Metadata
src/registry/hooks/meta.json, src/registry/hooks/use-local-storage-state/registry-item.json
Registers use-local-storage-state in hooks metadata and adds a registry item JSON with empty registryDependencies.

Sequence Diagram

sequenceDiagram
    participant Component
    participant Hook as useLocalStorageState
    participant LocalStorage
    participant Sync as useSyncExternalStore
    participant OtherTab as OtherTab

    Component->>Hook: call(key, initialValue, options)
    Hook->>LocalStorage: read key
    alt value present
        LocalStorage-->>Hook: serialized value
        Hook->>Hook: deserialize & cache
    else no value or SSR
        Hook->>Hook: use initialValue or in-memory fallback
    end
    Hook->>Sync: subscribe(storage events & local emitter)

    Component->>Hook: setValue(new)
    Hook->>Hook: serialize (options.serializer)
    Hook->>LocalStorage: write key
    Hook->>Hook: update cache & emit LOCAL_STORAGE_STATE_EVENT
    Sync-->>Hook: notify subscribers
    Hook-->>Component: updated state

    OtherTab->>LocalStorage: write same key
    LocalStorage-->>Hook: storage event
    Sync-->>Hook: notify
    Hook->>Hook: deserialize & update cache
    Hook-->>Component: synced state

    Component->>Hook: removeValue()
    Hook->>LocalStorage: remove key
    Hook->>Hook: reset cache to initialValue & emit event
    Hook-->>Component: cleared state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I nibble bytes and guard your state so neat,
I bind the name, I clear, I keep cache fleet,
Tabs hum in tune, SSR sleeps safe and sound,
A little rabbit hops—your values all around! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 9.09% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly describes the main change: adding a new useLocalStorageState hook to the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/use-local-storage-state

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/registry/hooks/use-hash/demo/demo-01.tsx`:
- Around line 36-40: The Input field using value={inputValue} and
onChange={setInputValue} with placeholder='Type hash without #' lacks an
accessible label; add an explicit label (e.g., a <label> or
aria-label/aria-labelledby) tied to this Input so assistive tech can identify it
— ensure the label references the Input (use htmlFor/id or aria-labelledby) and
use a clear name like "Hash" or "Hash (without #)" while keeping the existing
placeholder and props.

In `@src/registry/hooks/use-local-storage-state/index.mdx`:
- Line 3: Update the description line in the MDX frontmatter for
use-local-storage-state so it reads "An SSR-safe behavior" instead of "A
SSR-safe behavior" — locate the description field in
src/registry/hooks/use-local-storage-state/index.mdx and change the leading
article from "A" to "An".

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7e9b1ae and 3e5d58e.

📒 Files selected for processing (11)
  • content/docs/introduction.mdx
  • skills/shadcn-hooks/SKILL.md
  • skills/shadcn-hooks/references/useLocalStorageState.md
  • src/registry/hooks/meta.json
  • src/registry/hooks/use-hash/demo/demo-01.tsx
  • src/registry/hooks/use-hash/index.mdx
  • src/registry/hooks/use-local-storage-state/demo/demo-01.tsx
  • src/registry/hooks/use-local-storage-state/index.mdx
  • src/registry/hooks/use-local-storage-state/index.test.ts
  • src/registry/hooks/use-local-storage-state/index.ts
  • src/registry/hooks/use-local-storage-state/registry-item.json
🔥 Files not summarized due to errors (1)
  • content/docs/introduction.mdx: Error: Server error: no LLM provider could handle the message

@@ -0,0 +1,56 @@
---
title: useLocalStorageState
description: A hook to persist state in localStorage with SSR-safe behavior
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix article in description text.

Line 3 should read “An SSR-safe...” instead of “A SSR-safe...”.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/registry/hooks/use-local-storage-state/index.mdx` at line 3, Update the
description line in the MDX frontmatter for use-local-storage-state so it reads
"An SSR-safe behavior" instead of "A SSR-safe behavior" — locate the description
field in src/registry/hooks/use-local-storage-state/index.mdx and change the
leading article from "A" to "An".

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/registry/hooks/use-hash/demo/demo-01.tsx`:
- Around line 20-24: The setHash function currently prepends a '#' without
normalizing input; update setHash to first trim whitespace and strip any leading
'#' characters from the incoming value (e.g., normalize =
value.trim().replace(/^#+/, '')), then build nextHash using the normalized
string (nextHash = normalized ? `#${normalized}` : '') and call
window.location.assign as before; reference the setHash function to apply this
change.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3e5d58e and 27c2f26.

📒 Files selected for processing (1)
  • src/registry/hooks/use-hash/demo/demo-01.tsx

Comment on lines +20 to +24
const setHash = (value: string) => {
const nextHash = value ? `#${value}` : ''
window.location.assign(
`${window.location.pathname}${window.location.search}${nextHash}`,
)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Normalize user input before building the hash fragment.

If users type a leading #, Line 21 prepends another one and creates ##... in the URL fragment. Strip leading hashes (and whitespace) first.

Proposed fix
   const setHash = (value: string) => {
-    const nextHash = value ? `#${value}` : ''
+    const normalized = value.trim().replace(/^#+/, '')
+    const nextHash = normalized ? `#${normalized}` : ''
     window.location.assign(
       `${window.location.pathname}${window.location.search}${nextHash}`,
     )
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const setHash = (value: string) => {
const nextHash = value ? `#${value}` : ''
window.location.assign(
`${window.location.pathname}${window.location.search}${nextHash}`,
)
const setHash = (value: string) => {
const normalized = value.trim().replace(/^#+/, '')
const nextHash = normalized ? `#${normalized}` : ''
window.location.assign(
`${window.location.pathname}${window.location.search}${nextHash}`,
)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/registry/hooks/use-hash/demo/demo-01.tsx` around lines 20 - 24, The
setHash function currently prepends a '#' without normalizing input; update
setHash to first trim whitespace and strip any leading '#' characters from the
incoming value (e.g., normalize = value.trim().replace(/^#+/, '')), then build
nextHash using the normalized string (nextHash = normalized ? `#${normalized}` :
'') and call window.location.assign as before; reference the setHash function to
apply this change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant