I never used re-frame, so I can’t speak directly to it. But of the virtue of Clojure in general. If you look at it, Clojure doesn’t frown upon mutation, as long as it is thread safe, and encapsulated within a context.
That means that components shouldn’t be coupled to their environment, and thus they shouldn’t depend on finding things in external locations not under their control. It also means you should be able to reason independently of the rest of the application about the behavior of a component. That could extend therefore to testing it.
Shared state and mutation often fail at the above “virtue” of having independent components that do not depend on their environment or other components to have put things in the right place at the right time.
But you always need something to tie together such components, and orchestrate the data exchanged between them and their order of execution. A dataflow/workflow of some sort, describing the structure and the timings of the components together, and their interaction with the user of the application.
This application framework, Clojure tends to be okay with it performing side effects and using global state. This is often where Clojure distinguishes itself as an impure functional language. It allows the application framework to break purity, while strongly pushing for the components to maintain it.
Since I know nothing of re-frame, I don’t know where it stands within this view. If it acts as such an application framework for independent components, then I’d say it would follow along. If it doesn’t, it is probably breaking with the Clojure mentra somewhat, but hey, if it makes you productive, results in low defect code, remains open to painfree and quick future evolution and extension (adding new features to your app), and makes things understandable and easy to debug, maybe it doesn’t matter.