Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Reaction instance gets reused after dispose #553

Closed
isaksky opened this issue Oct 1, 2019 · 4 comments
Closed

Reaction instance gets reused after dispose #553

isaksky opened this issue Oct 1, 2019 · 4 comments
Assignees

Comments

@isaksky
Copy link

isaksky commented Oct 1, 2019

Let's say I have a component that uses this subscription when it is focused:

(rf/reg-sub-raw
  :my-value-sub
  (fn [app-db _]
    (do-my-side-effect! true)
    (let [my-value-cursor (ra/cursor app-db [:my-value])]
      (ra/make-reaction 
        (fn [] @my-value-cursor)
        :on-dispose #(do-my-side-effect! false)))))

If I blur the field, (do-my-side-effect! false) will be called (via :on-dispose). If I then focus the field again, the same subscription instance is reused, but there is no way to know that (do-my-side-effect! true) needs to be called again. (Or is there?)

If a fresh instance of the reaction was created, this problem would go away. (Though I don't know if this would cause other problems).

This problem can be worked around by doing these side-effects in the event-handlers instead (e.g., via on-blur and on-focus in this case), though it may require duplicating logic.

@isaksky
Copy link
Author

isaksky commented Oct 1, 2019

The problem was made possible by use of this pattern:

(defn child-component [some-sub]
  [:pre (pr-str @some-sub)])

(defn parent-component []
  [child-component (rf/subscribe [:some-sub])])

The problem is if the parent does not re-render, the same instance of the reaction will be used (even though it has been disposed).

Switching to this pattern (send sub-path instead of actual sub) fixes it:

(defn child-component [some-sub-path]
  [:pre (pr-str @(rf/subscribe some-sub-path))])

(defn parent-component []
  [child-component [:some-sub]])

@lilactown
Copy link

In the case that you do want to subscribe in the child component, but want the parent to control the subscription used, you might be able to pass in a function that returns the subscription instead. E.g.

(defn child-component [create-some-sub]
  [:pre (pr-str @(create-some-sub))])

(defn parent-component []
  [child-component #(rf/subscribe [:some-sub])])

I haven't tested this but it would seem to solve the problem where the reaction is persisted despite being disposed, as each render of child-component would call subscribe again.

@isaksky
Copy link
Author

isaksky commented Nov 15, 2019

@Lokeh Yea - in my bottom example, I achieve the same result by just passing the sub-path instead of the subscription, then call subscribe from the child, and that works.

@superstructor superstructor self-assigned this May 4, 2020
@superstructor
Copy link
Contributor

To my eyes, this is certainly an odd, slightly scary mix of cursors and reg-sub-raw and side-effects. There’s nothing very idiomatic to re-frame going on here. There must be a waaaaaay easier way of doing whatever it is that you are doing. See /Support.md in the root of this repo.
I’m going to close this because, although you might well be right with your report, I’m not sure what I can or should do to fix whatever problem you might have found.

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

No branches or pull requests

3 participants