Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

gensym / anonymous function syntax breaks fast refresh #117

Open
SevereOverfl0w opened this issue Dec 18, 2022 · 2 comments
Open

gensym / anonymous function syntax breaks fast refresh #117

SevereOverfl0w opened this issue Dec 18, 2022 · 2 comments

Comments

@SevereOverfl0w
Copy link
Contributor

Simple reproduction that will cause fast refresh to always do a full reload:

(defnc ...
  (hooks/use-effect
    []
    (run-my-callback #(identity %)))
  ...)

It will be fixed by using (fn [%] (identity %)) instead. The problem is that on each reload the gensym'd binding that replaces % is changed. Compare:

(hooks/use-effect [] (reitit.frontend.easy/start! (reitit.frontend/router []) (fn* [p1__27869#] (identity p1__27869#)) {:use-fragment false})) 
;; vs
(hooks/use-effect [] (reitit.frontend.easy/start! (reitit.frontend/router []) identity {:use-fragment false}))

I don't have an clear idea on how to best fix this. If there was a way to detect & remove gensym'd symbols, that would be ideal. I don't know think that's possible at all.

The anonymous function syntax seems likely to be the most common (only? is this something that can only happen from syntax, or could a macro cause it too?) cause of this and it will always end its binding with #, or you could pick up on the prefix of p\d+__ for that case, too.

@lilactown
Copy link
Owner

Thanks for the report.

I haven't tested this, but since it's the defnc macro that does the fast-refresh detection, I think this is only a problem for things that gensym new bindings in the reader. E.g. if you have a macro that gensyms some binding,

(defnc my-component
  []
  (hooks/use-effect [] (my-thing-that-generates-some-bindings-internally))
  ,,,)

The code used by defnc will be the non-macro-expanded forms. It's only because the anonymous function syntax expansion happens in the reader that this is a problem. I think.

Based on my reading here https://github.com/clojure/tools.reader/blob/fb185af411fa379e48e5d0a9e623b68f552d8c92/src/main/clojure/clojure/tools/reader.clj#L528-L532 I think that detecting the # at the end of the binding seems easiest.

PR welcome!

@roman01la
Copy link

roman01la commented Oct 3, 2023

FYI I had a similar issue in UIx, here's the fix, perhaps it can help pitch-io/uix@7c39a4e

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants