Fork me on GitHub
#clojurescript
<
2024-05-16
>
Pablo21:05:13

Hello I’m trying to rewrite this example on ClojureScript http://reactcommunity.org/react-transition-group/switch-transition, but when I add :node-ref to CSSTransition it stops working:

(defn app []
  (let [state (r/atom true)
        node-ref (r/atom nil)]
    (fn []
      [:> SwitchTransition
       [:> CSSTransition {:key        @state
                          :class-names :fade
                          :timeout    500}
        [:div {:ref (fn [node] (reset! node-ref node))}
         [:button {:on-click (fn [_] (swap! state not))}
          (if @state
            "Hello, world!"
            "Goodbye, world!")]]]])))
I just add :node-ref @node-ref. Any idea of how I can use refs ?

phill22:05:01

Isn't it supposed to be (not an atom but) a function which in turn can reset the atom?

Pablo22:05:40

I don’t think so > nodeRef > A React reference to the DOM element that needs to transition: https://stackoverflow.com/a/51127130/4671932

Ben Lieberman01:05:26

why not just use a React ref with createRef?

anssikin08:05:15

i recently also implemented reagent component that uses CSSTransition. i can't remember exact details why i got node-ref working with ref hook but not with createRef , maybe it was something wrong with my state management. i wanted to use :addEndListener to control animation length from CSS. so something like

(let [node-ref (react/useRef nil)]
  [:> CSSTransition {:nodeRef node-ref ...}])
and wrap as function component [:f> ...] when using

Pablo15:05:06

I want to use more than 3 elements that use that transition, so I was thinking of using a map to store the refs depending on the key. The problem comes when I try to translate this part:

const helloRef = React.useRef(null);
  const goodbyeRef = React.useRef(null);
  const nodeRef = state ? helloRef : goodbyeRef;
Because of the state ? helloRef : goodbyeRef part

Pablo15:05:32

I also observed that when using a ratom it enters a loop, since when :ref is invoked to store the reference, this subsequently renders the component again because it is used as a parameter in the CSSTransition

Pablo15:05:22

I already tried with an atom, but it doesn’t work either

Pablo15:05:14

Here is the actual implementation:

(defn animation []
  (let [state       (r/atom false)
        hello-ref   (useRef nil)
        goodbye-ref (useRef nil)]
    (fn []
      (let [node-ref (if @state hello-ref goodbye-ref)]
        [:> SwitchTransition
         [:> CSSTransition {:key              @state
                            :node-ref         node-ref
                            :add-end-listener (fn [done]
                                                (-> node-ref .current (.addEventListener "transitionend" done false)))

                            :class-names      :fade}

          [:div {:ref node-ref}
           ^{:key @state}
           [:button {:on-click (fn [_] (swap! state not))}
            (if @state
              "Hello, world!"
              "Goodbye, world!")]]]]))))


(defn app []
  [:f> animation])
But I get this error: Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement. 😞

Ben Lieberman20:05:51

I don't think it will necessarily solve your issue but I do believe that refs return a JS object with a current field, so you should be accessing it with .-current and not .current

👍 2