Skip to content

fix(store): run compare when the previous atom value is undefined - #403

Open
mbret wants to merge 2 commits into
TanStack:mainfrom
mbret:fix/atom-compare-undefined
Open

mbret wants to merge 2 commits into
TanStack:mainfrom
mbret:fix/atom-compare-undefined

Conversation

@mbret

@mbret mbret commented Oct 27, 2026 •

Copy link
Copy Markdown

🎯 Changes

Atoms skip compare whenever their previous value is undefined, so a computed atom that stays undefined notifies its subscribers on every recompute.

const stack = createAtom<Array<number>>([])
const top = createAtom(() => stack.get().at(-1))
top.subscribe(() => console.log('notified'))
stack.set([]) // logs "notified" although `top` is still undefined
  • Cause: _update reads an undefined previous snapshot as "this computed atom has not computed yet" so that a custom compare never sees an uncomputed snapshot. undefined is also a valid snapshot, so the check fires for every atom that holds undefined, and compare never runs for it. createAtom(undefined, { compare: () => true }).set(1) applies the write.
  • Fix: a hasSnapshot flag tracks whether a computed atom has computed yet. The first computation still skips compare.
  • Tests: tests/undefined-snapshot.test.ts. The first two cases fail on main and pass with the fix. The third pins that compare is not called before the first computation.

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested code changes locally with pnpm test:pr, or these tests do not apply to this pull request.
  • I fully understand the code in this pull request, including any code generated with AI assistance.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

🤖 Generated with Claude Code

https://claude.ai/code/session_01BvSDyHMgrdgjFz8EAk5VKo

Summary by CodeRabbit

  • Bug Fixes
    • Computed values that return undefined are now handled consistently. The first computation stores its result, while later unchanged undefined results do not repeatedly notify subscribers. Custom comparison rules can determine whether a result should be treated as an update, including when the previous value is undefined. By default, value comparisons continue to use standard identity checks.

`_update` treated an `undefined` previous snapshot as "nothing to compare
against yet" so a custom `compare` never saw a computed atom's
uncomputed snapshot. `undefined` is also a valid snapshot, though, so a
computed atom that keeps returning `undefined` notified its subscribers on
every recompute, and `compare` never ran while an atom held `undefined`.
Track whether a computed atom has computed yet instead.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvSDyHMgrdgjFz8EAk5VKo
@changeset-bot

changeset-bot Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: f72cae0

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

This PR includes changesets to release 9 packages
Name Type
@tanstack/store Patch
@tanstack/angular-store Patch
@tanstack/lit-store Patch
@tanstack/octane-store Patch
@tanstack/preact-store Patch
@tanstack/react-store Patch
@tanstack/solid-store Patch
@tanstack/svelte-store Patch
@tanstack/vue-store 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

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 27, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-27T12:46:51.811084Z ff8b25b PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between ff8b25b and f72cae0.

Files selected for processing: 1
  • packages/store/src/atom.ts

Included review availability: This review used your included allowance. Your plan provides up to 4 included reviews per hour; 1 remain after this review.

Walkthrough

Computed atoms now store their first result, including undefined, without running the comparator. Later results use the configured comparator or Object.is. Tests cover repeated undefined results, custom comparator behavior, and the first computation.

Changes: Computed atom snapshot comparison

Layer / File(s) Summary
First snapshot and subsequent comparisons
packages/store/src/atom.ts, packages/store/tests/undefined-snapshot.test.ts, .changeset/atom-compare-undefined.md
Computed atoms track whether a snapshot exists. The first result is stored without comparison; later results use the comparator. Tests cover undefined results, subscriber notifications, and the first computation. The changeset describes the comparison behavior.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

  • TanStack/store#402: Both changes define how atom updates handle undefined values and snapshots.

Suggested reviewers: davidkpiano

Merge Risk: Minimal · up to f72ca

The change preserves the intended computed-atom comparison and notification behavior, with no merge-blocking risk established.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within survi… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Description check Passed The description follows the required template. It explains the change, cause, fix, tests, checklist status, and release impact. It also includes a changeset reference.
Title check Passed The title clearly and concisely describes the main change: running atom comparisons when the previous value is undefined.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 1 functions across 2 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches
🧪 Generate unit tests (beta)
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

`isFirstComputation` says what the guard is for, so the flag needs no
comment to explain it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BvSDyHMgrdgjFz8EAk5VKo
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.

2 participants