There is plenty of state going on in the react code and yes on the surface you just have a nice clean render declaration. But when you start to want to express complicated animations but insist on doing things by the React Bible (ie no dirty refs) it can easily become worse than the imperative solution with performance degradation s and difficult to understand code that is deceptive ly simple but leaves a lot of complexity poorly expressed. Even in this article itself ,which takes great pains to hype up the react way or the highway, the manner it handles exit animations in React shows that the abstraction is already leaking.
Normally, if you are writing something so weird that it needs to be imperative to be readable or work right, you can just do that inside a useEffect, or at least encapsulate it in a component. For most animations, ReactCSSTransitionGroup is sufficient. This is an interesting case study only because D3 is particular about wanting data to be stored in the DOM, and React is particular about wanting the data to be stored anywhere but the DOM. I am curious though what you mean by dirty refs?
oh I guess that is confusing, I just meant to invoke the attitude of react purists to using refs (like in the article), although imo it is sometimes the best and 'cleanest' way of expressing what you want to do