Skip to content

fix: useeffect should not return subscription object#416

Open
vilindh wants to merge 1 commit intoTanStack:mainfrom
vilindh:fix-useffect-erroneous-return
Open

fix: useeffect should not return subscription object#416
vilindh wants to merge 1 commit intoTanStack:mainfrom
vilindh:fix-useffect-erroneous-return

Conversation

@vilindh
Copy link
Copy Markdown

@vilindh vilindh commented Mar 28, 2026

This PR fixes an issue with useEffect hook faulty returning a subscription object;
useEffect should not return, unless a cleanup function.

Current implication of return is that navigating to "Meet Our Speakers" from the tryout example starting page, results
in a crash-landing.

Summary by CodeRabbit

  • Bug Fixes
    • Fixed state synchronization handling in the Assistant component to ensure proper effect cleanup behavior.

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 28, 2026

📝 Walkthrough

Walkthrough

Removed a return statement from a showRemyAssistant.subscribe(...) call in an effect within the RemyAssistant component. The effect continues to invoke subscribe and set state on updates but no longer returns the disposer function.

Changes

Cohort / File(s) Summary
RemyAssistant Component Effect
packages/create/src/frameworks/react/examples/events/assets/src/components/RemyAssistant.tsx
Removed return statement from showRemyAssistant.subscribe(...) call in header-control synchronization effect; cleanup function no longer returned while state updates remain intact.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A hop and a skip, the return takes a slip,
No cleanup to keep, just state in its grip,
The subscribe still glows, as the assistant now flows,
A subtle refine where the change gently goes! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ 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%. 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 PR title directly addresses the main change: removing an erroneous subscription object return from a useEffect hook to fix a navigation crash.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@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
`@packages/create/src/frameworks/react/examples/events/assets/src/components/RemyAssistant.tsx`:
- Around line 93-97: The useEffect in RemyAssistant subscribes to
showRemyAssistant but does not return the unsubscribe function, causing
lingering listeners; update the effect that calls
showRemyAssistant.subscribe(...) to capture the returned unsubscribe (or
subscription) and return it from the useEffect cleanup so the listener is
removed on unmount (match the pattern used in ResumeAssistant.tsx around its
subscription); ensure you still call setIsOpen(showRemyAssistant.state) on
subscription events and return the unsubscribe function from useEffect.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 096d44e8-5af6-47dd-b732-afcbab5a1198

📥 Commits

Reviewing files that changed from the base of the PR and between 40b9c12 and 7a18630.

📒 Files selected for processing (1)
  • packages/create/src/frameworks/react/examples/events/assets/src/components/RemyAssistant.tsx

Comment on lines 93 to 97
useEffect(() => {
return showRemyAssistant.subscribe(() => {
showRemyAssistant.subscribe(() => {
setIsOpen(showRemyAssistant.state)
})
}, [])
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Compare effect patterns in related components.
rg -n --type=tsx -C2 'show(Remy|Resume)Assistant\.subscribe' packages/create/src/frameworks/react/examples

# 2) Find the `@tanstack/store` version used by the repo.
dep=$(rg -n --no-heading '"@tanstack/store"\s*:\s*"[^"]+"' --glob '**/package.json' | head -n1 | sed -E 's/.*"@tanstack\/store"\s*:\s*"([^"]+)".*/\1/')
ver=$(printf '%s' "$dep" | sed -E 's/^[^0-9]*//')
echo "Detected `@tanstack/store` range: $dep (normalized: $ver)"

# 3) Inspect published typings/source for subscribe signature in that version.
for url in \
  "https://unpkg.com/@tanstack/store@${ver}/dist/esm/index.d.ts" \
  "https://unpkg.com/@tanstack/store@${ver}/build/lib/index.d.ts" \
  "https://unpkg.com/@tanstack/store@${ver}/src/index.ts"
do
  echo "Checking $url"
  if curl -fsSL "$url" | rg -n 'subscribe\s*\(' -C2; then
    echo "Signature found in $url"
    break
  fi
done

Repository: TanStack/cli

Length of output: 83


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# 1) Fix: Use proper glob pattern instead of unrecognized --type=tsx
echo "=== Searching for subscription patterns in React example components ==="
rg -n -C2 'show(Remy|Resume)Assistant\.subscribe' packages/create/src/frameworks/react/examples --type-list | head -5 || true
rg -n -C2 'show(Remy|Resume)Assistant\.subscribe' packages/create/src/frameworks/react/examples -g '*.tsx' 2>/dev/null || echo "Pattern not found with -g flag, trying without type restriction"
rg -n -C2 'show(Remy|Resume)Assistant\.subscribe' packages/create/src/frameworks/react/examples || echo "No matches found"

Repository: TanStack/cli

Length of output: 3098


🏁 Script executed:

#!/bin/bash
# Read the target file to see the actual code at lines 93-97
echo "=== RemyAssistant.tsx (lines 85-105) ==="
cat -n packages/create/src/frameworks/react/examples/events/assets/src/components/RemyAssistant.tsx | sed -n '85,105p'

Repository: TanStack/cli

Length of output: 795


🏁 Script executed:

#!/bin/bash
# Read the comparison file mentioned in the review
echo "=== ResumeAssistant.tsx (lines 75-95) ==="
cat -n packages/create/src/frameworks/react/examples/resume/assets/src/components/ResumeAssistant.tsx | sed -n '75,95p'

Repository: TanStack/cli

Length of output: 839


🏁 Script executed:

#!/bin/bash
# Find the `@tanstack/store` version in package.json
echo "=== `@tanstack/store` version ==="
rg '"@tanstack/store"' -g '**/package.json' -A1 packages/create

Repository: TanStack/cli

Length of output: 839


🏁 Script executed:

#!/bin/bash
# Search for `@tanstack/store` documentation or type definitions in the repo
echo "=== Checking if `@tanstack/store` types are available in node_modules or lockfile ==="
find . -name "package-lock.json" -o -name "yarn.lock" -o -name "pnpm-lock.yaml" | head -3

# Check if there are any existing imports or usage patterns in the repo
echo "=== Checking other Store.subscribe usages in codebase ==="
rg 'subscribe\s*\(' packages/ --max-count=10 -B2 -A2 || echo "No other patterns found"

Repository: TanStack/cli

Length of output: 4547


🌐 Web query:

@tanstack/store subscribe method return type API documentation

💡 Result:

The subscribe method on Store instances from @tanstack/store returns a Subscription object. This object has an unsubscribe method: unsubscribe: => void. Signature: subscribe(observerOrFn: Observer | (value: T) => void): Subscription Subscription interface: interface Subscription { unsubscribe: => void; } Examples from docs: const subscription = store.subscribe((value) => { ... }); subscription.unsubscribe; This is consistent across Store, ReadonlyStore, Atom, etc. as they extend Subscribable.

Citations:


Return the unsubscribe function to ensure effect cleanup on unmount.

Line 94 subscribes to the store without returning the cleanup function. This causes listeners to persist after unmount, leading to memory leaks and duplicate subscriptions on remounts. Compare with ResumeAssistant.tsx:84 which correctly returns the subscription.

Proposed fix
   // Sync with store for header control
   useEffect(() => {
-    showRemyAssistant.subscribe(() => {
+    const unsubscribe = showRemyAssistant.subscribe(() => {
       setIsOpen(showRemyAssistant.state)
     })
+    return unsubscribe
   }, [])
📝 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
useEffect(() => {
return showRemyAssistant.subscribe(() => {
showRemyAssistant.subscribe(() => {
setIsOpen(showRemyAssistant.state)
})
}, [])
useEffect(() => {
const unsubscribe = showRemyAssistant.subscribe(() => {
setIsOpen(showRemyAssistant.state)
})
return unsubscribe
}, [])
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@packages/create/src/frameworks/react/examples/events/assets/src/components/RemyAssistant.tsx`
around lines 93 - 97, The useEffect in RemyAssistant subscribes to
showRemyAssistant but does not return the unsubscribe function, causing
lingering listeners; update the effect that calls
showRemyAssistant.subscribe(...) to capture the returned unsubscribe (or
subscription) and return it from the useEffect cleanup so the listener is
removed on unmount (match the pattern used in ResumeAssistant.tsx around its
subscription); ensure you still call setIsOpen(showRemyAssistant.state) on
subscription events and return the unsubscribe function from useEffect.

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