Do you want to request a feature or report a bug?
Bug
What is the current behavior?
If a component implements a requestAnimationFrame loop and calls setState inside it, it will endlessly create listeners on the page as shown in the picture below:
https://i.imgur.com/6MN5JQc.png (Chrome Developer Tools)
While I understand that React 16 uses rAF for its reconciliation algorithm, running multiple rAF should work without producing the above behavior. From my understanding, all rAF callbacks will be appended to the next frame's callstack.
If the current behavior is a bug, please provide the steps to reproduce and if possible a minimal demo of the problem
Here is the minimal code required to trigger this behavior in React16: https://jsfiddle.net/cristidrg/Luktwrdm/29/
Profiling this fiddle will produce the same result as in the previous picture.
What is the expected behavior?
In React 15.6.2 this behavior does not happen, running the same code will not produce any unwanted listeners as seen in the picture below: https://i.imgur.com/EBhiE6p.png
Which versions of React, and which browser / OS are affected by this issue? Did this work in previous versions of React?
This was tested in React 16.0.0 on Ubuntu 16.04 with Chrome 57.0.2987.98. The behavior did not happen in previous versions of React.
React 16 doesn't use rAF. (At least not 16.0.0)
Good to know !
However it still seems like in 16.0.0 it creates listeners on the page when calling setState from a rAF loop, while in the prior versions it didn't. The chrome profiler does not let me see where are these listeners attached unfortunately.
I have tried testing on other browsers also, but they don't list the total number of listeners on the page.
If I run it long enough I do see them getting GC’d eventually:

You can also see it doesn’t happen in production mode at all:
https://jsfiddle.net/toqmgh30/

So I don’t think there is a real leak here. It is expected that we create more listeners because of this trick we use to intercept exceptions while keeping “Pause on Uncaught Exceptions” checkbox working. Maybe we could restructure that code to reuse a single listener and keep a stack of callers, but not sure it’s worth the effort.
Thanks for the clarification!
I'll close this issue.
Most helpful comment
If I run it long enough I do see them getting GC’d eventually:
You can also see it doesn’t happen in production mode at all:
https://jsfiddle.net/toqmgh30/
So I don’t think there is a real leak here. It is expected that we create more listeners because of this trick we use to intercept exceptions while keeping “Pause on Uncaught Exceptions” checkbox working. Maybe we could restructure that code to reuse a single listener and keep a stack of callers, but not sure it’s worth the effort.