Skip to content

fix(useStorageState): reset to the default value when another tab clears the storage - #482

Merged
hyesungoh merged 1 commit into
toss:mainfrom
chungyo:fix/storage-clear-sync
Sep 8, 2026
Merged

hyesungoh merged 1 commit into
toss:mainfrom
chungyo:fix/storage-clear-sync

Conversation

@chungyo

@chungyo chungyo commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Overview

다른 탭에서 localStorage.clear()를 호출했을 때 useStorageState에 이전 값이 남는 문제를 수정합니다. 이제 새로고침이나 반환된 refresh 호출 없이 defaultValue로 돌아가며, 기본값이 없으면 undefined가 됩니다.

재현 방법

  1. 같은 origin의 탭 A에서 localStorage.setItem('name', JSON.stringify('Alice'))로 값을 저장한 뒤 아래 hook을 마운트합니다.

    const [name] = useStorageState<string>('name', { defaultValue: 'Guest' });
  2. 탭 B에서 localStorage.clear()를 실행합니다.

  3. 저장소는 비워지지만, 수정 전에는 탭 A의 name이 'Alice'로 남습니다. 기대값은 'Guest'입니다.

clear()로 전달되는 storage 이벤트의 key는 null입니다. 기존 구독 조건은 관찰 중인 key와 정확히 일치하는 이벤트만 처리하므로 전체 삭제를 놓칩니다. (HTML 표준)

변경 내용

  • key가 null인 이벤트에도 구독자를 깨워 기존 snapshot 로직으로 저장소를 다시 읽습니다.
  • 이벤트의 newValue를 직접 적용하지 않으므로, 다른 종류의 저장소가 비워져도 hook이 사용하는 저장소의 값은 유지됩니다.
  • 기본값 유무, 다른 저장소의 전체 삭제, 관찰 key 삭제, 무관한 key 삭제를 확인하는 테스트 5개와 patch changeset을 추가합니다.

검증

  • 추가한 전체 삭제 테스트 2개가 수정 전 실패하고, 수정 후 useStorageState 테스트 53개가 모두 통과했습니다. 기존 SSR 검증도 포함됩니다.
  • Chromium 152의 같은 origin 두 페이지에서 실제 localStorage.clear()를 실행했습니다. isTrusted: true, key: null 이벤트가 도착한 뒤 기본값이 있는 hook은 기본값으로, 없는 hook은 undefined로 갱신됐습니다.
  • yarn run test:coverage: 통과. 라이브러리 테스트 579개 통과, useStorageState.ts와 storage.ts의 실행 구문 커버리지 100%.
  • yarn run test:compiled: 581개 통과.
  • test:format, test:lint, test:type, test:docs, test:skill, test:codemod, verify:compiler, verify:pack: 통과.

로컬 검증 환경: Node 24.19.0, Yarn 4.18.0, React 19.1.0.

Checklist

  • Did you write the test code?
  • Have you run yarn run fix to format and lint the code and docs?
  • Have you run yarn run test:coverage to make sure there is no uncovered line?
  • JSDoc 확인 — 기존 설명이 수정 후 동작과 일치합니다. 공개 API 변경이 없어 문서 변경은 필요하지 않습니다.

Copilot AI lite review requested due to automatic review settings September 8, 2026 04:18
@changeset-bot

changeset-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: efa112d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
react-simplikit Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Approval recommended

The change is minimal, aligns with the Web Storage event semantics (key: null on clear), and is backed by focused regression tests.

Pull request overview

Fixes useStorageState so it correctly reacts when another tab clears storage via localStorage.clear() (which emits a storage event with key: null), ensuring the hook resets to defaultValue (or undefined) without requiring a refresh.

Changes:

  • Treat StorageEvent.key == null as a relevant event and trigger a snapshot refresh.
  • Add regression tests covering localStorage.clear() behavior, cross-storage clearing, observed-key removal, and unrelated-key removal.
  • Add a patch changeset describing the fix.
File summaries
File Description
packages/react-simplikit/src/hooks/useStorageState/useStorageState.ts Updates the storage-event filter to also handle key: null events (storage clear).
packages/react-simplikit/src/hooks/useStorageState/useStorageState.spec.ts Adds targeted tests to validate reset/preserve behavior for clear/remove events across tabs and storage areas.
.changeset/fix-storage-clear-sync.md Patch changeset documenting the bug fix.
Review details
  • Files reviewed: 3/3 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (6f6361c) to head (efa112d).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff            @@
##              main      #482   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files           69        69           
  Lines         2233      2233           
  Branches       717       718    +1     
=========================================
  Hits          2233      2233           
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@hyesungoh hyesungoh changed the title fix(useStorageState): 다른 탭의 저장소 전체 삭제를 상태에 반영 fix(useStorageState): reset to the default value when another tab clears the storage Sep 8, 2026

@hyesungoh hyesungoh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks to your contribution! 👍

@hyesungoh
hyesungoh merged commit 163ac5c into toss:main Sep 8, 2026
20 checks passed
@github-actions github-actions Bot mentioned this pull request Sep 8, 2026
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.

4 participants