Skip to content

fix: cleanup event-emitter subscriptions in provider hooks#392

Open
Zaimwa9 wants to merge 1 commit intomainfrom
fix/react-subscription-leak
Open

fix: cleanup event-emitter subscriptions in provider hooks#392
Zaimwa9 wants to merge 1 commit intomainfrom
fix/react-subscription-leak

Conversation

@Zaimwa9
Copy link
Copy Markdown
Contributor

@Zaimwa9 Zaimwa9 commented Apr 20, 2026

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Closes #390
Hooks were rendering at render time instead than in an effect and the cleanup paths did not remove all registered listeners

  • useFlagsmithLoading and useFlags: subscribe inside useEffect with emitter.on's returned unsubscribe as cleanup. Removes render-time events.on and multi subscription

How did you test this code?

Branch Active listeners after 1000 SSR renders
main (pre-fix) 2000 (2 leaked per render: one from useFlagsmithLoading, one from useFlags)
fix/react-subscription-leak 0

@Zaimwa9 Zaimwa9 requested a review from a team as a code owner April 20, 2026 13:57
@Zaimwa9 Zaimwa9 requested review from kyle-ssg and talissoncosta and removed request for a team and kyle-ssg April 20, 2026 13:57
Copy link
Copy Markdown
Contributor

@talissoncosta talissoncosta left a comment

Choose a reason for hiding this comment

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

Looks good, just one question. Not blocking

Comment thread react.tsx
useEffect(() => {
if (!flagsmith) return
setRenderRef(getRenderKey(flagsmith, flags, traits))
const unsubscribe = events.on('event', () => {
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.

Quick question: was the switch from events.once => events.on intentional?

Just want to make sure you're aware it's a behavior change: in the old code each render re-registered a once listener (because useRef's arg evaluates every render), so the hook reacted on every emit incidentally.

With events.on, it's a single persistent subscription. Same net behavior for consumers as far as I can tell, but wanted to flag it in case you hadn't spotted it.

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.

React hooks leak event-emitter subscriptions, causing CPU growth on Vercel Fluid Compute

2 participants