Giter Site home page Giter Site logo

Comments (23)

gadfly361 avatar gadfly361 commented on May 7, 2024 2

https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/ReactCSSTransitionGroup

from reagent.

AlexanderWingard avatar AlexanderWingard commented on May 7, 2024 2

@dmkolobov
I'm interested, did you ever get this to work?

from reagent.

loganpowell avatar loganpowell commented on May 7, 2024 2

I thought others might be interested in a relatively new animation library for React that allows indirect children communication:

https://popmotion.io/pose/learn/animating-children/

Whenever a posed component changes pose, that change is communicated throughout all of its children posed components via React’s context API. So even if they’re not direct children, they still update accordingly.

From the horse's mouth

Functional composition: Don't wait for the library authors to offer new features via configs. Use pure functions to compose your own.

This is a key note that makes me think it would be the best fit for Clojurists:

Pose can create animations based on the properties being animated.

from reagent.

dmkolobov avatar dmkolobov commented on May 7, 2024 1

On a related note, does anyone know if stateful animation via ReactTransition group is supported?

I'm trying to build an animated accordion-like component, and I need to set the max-height to a know value to prevent animation delay when the content collapses. Based on my understanding of the React docs, the baked in 'CSSTransitionGroup' is insufficient for this.

So I made two components:

(defn accordion-content
  [content]
  (reagent/create-class
   {:component-will-enter 
     (fn [cb] (println "entering")}) (cb))
    :component-did-enter
      #(println "entered")
    :component-will-leave ;; set max-height here
      (fn [cb] (println "leaving") (cb))
    :component-did-leave
      #(println "left")
    :reagent-render
      (fn [content] [:div content])}))

(def transition-group
  (reagent/adapt-class js/React.addons.TransitionGroup))

(defn accordion
  [expanded content]
  [:div
   [transition-group
    {:transition-name "accordion-expanding"}
    (map-indexed (fn [idx c] ^{:key idx} c)
                 (when @expanded? [accordion-content content]))])

Per the docs, whenever children are added/removed to the group, the special lifecycle methods above are invoked on the child. The lifecycle methods are never called in my example.

Am I missing something here? I know that reagent wraps each non-native component in another one. Is it possible that the accordion-content is wrapped in some component which intercepts the lifecycle invocations, or prevents the transform group from working properly?


EDIT: forgot reagent-render

from reagent.

Deraen avatar Deraen commented on May 7, 2024 1

New issue should be created about not being able to use ReactTransitionGroup.

from reagent.

Frozenlock avatar Frozenlock commented on May 7, 2024

On a related note, I don't see any animation on the TODO example, even if the animation CSS is there.

from reagent.

GetContented avatar GetContented commented on May 7, 2024

This would be pretty awesome. I wonder if there has been any further movement on this?

from reagent.

jcreedcmu avatar jcreedcmu commented on May 7, 2024

This appears to be doable as long as you depend on cljs/react-with-addons in your project, as described in https://github.com/reagent-project/reagent/blob/master/README.md

Here's some example code that does list item insertion and removal animations:

(defn without-nth [seq n]
  vec (concat (subvec seq 0 n) (subvec seq (+ 1 n))))

(def css-transition-group
  (reagent/adapt-react-class js/React.addons.CSSTransitionGroup))

(def style "

li {
  background-color: #44ee22; padding: 10px; margin: 1px; width: 150px;
  border-radius: 5px;
  font-size: 24px;
  text-align: center;
  list-style: none;
  color: #fff;
  height: 2em;
  line-height: 2em;
  padding: 0 0.5em;
  overflow: hidden;
}

.foo-enter {
  height: 0;
  transition: height 0.27s ease-out;
}

.foo-leave {
  height: 0;
  transition: height 0.27s ease-out;
}

.foo-enter-active {
  height: 2em;
  opacity: 1;
}")

(defn list-comp [items]
   [css-transition-group {:transition-name "foo"}
       (map-indexed (fn [i x] ^{:key x} [:li (str "List Item " x)]) @items)  ])

(defn main-comp []
  (let [items (atom ["a" "b" "c"])
        next-item (atom 0)
        adder (fn [position]
                (fn [e]
                  (do (swap! items #(vec (let [[bef aft] (split-at position %)]
                                           (concat bef [@next-item] aft))))
                      (swap! next-item inc))))
        deleter (fn [position]
                  (fn [e] (swap! items #(vec (without-nth % position)))))
        _ (js/setTimeout (adder 0) 300)
        _ (js/setTimeout (adder 2) 700)
        _ (js/setTimeout (adder 5) 1100)
        _ (js/setTimeout (deleter 0) 1600)
        _ (js/setTimeout (deleter 2) 2000)
        _ (js/setTimeout (deleter 2) 2400)]
    [:div
     [:button {:on-click (adder 0)} "add"]
     [:button {:on-click (deleter 0)} "remove"]
     [:style style]
     [:ul
      [list-comp items]]
     ]))

from reagent.

yogthos avatar yogthos commented on May 7, 2024

@gadfly361 might be an idea to create a recipe for this :)

from reagent.

gadfly361 avatar gadfly361 commented on May 7, 2024

@yogthos Agreed!

@jcreedcmu Would you be interested in creating a reagent-cookbook recipe for this?

from reagent.

gadfly361 avatar gadfly361 commented on May 7, 2024

@yogthos Just revisited this and should have recipe in the next couple of days.

from reagent.

yogthos avatar yogthos commented on May 7, 2024

@gadfly361 fantastic :)

from reagent.

GetContented avatar GetContented commented on May 7, 2024

<3

from reagent.

marcloyal3 avatar marcloyal3 commented on May 7, 2024

Good job @gadfly361

Could also be done in mount/unmount cycles, so I wonder what advantages this has over doing it in lifecycle callbacks.

from reagent.

GetContented avatar GetContented commented on May 7, 2024

@dmkolobov Isn't it just because you're missing any kind of render in your class? Maybe it'd be good to read https://github.com/Day8/re-frame/wiki/Creating-Reagent-Components - but perhaps I'm missing something :) H2H

from reagent.

dmkolobov avatar dmkolobov commented on May 7, 2024

Whoops, @JulianLeviston forgot to add in the example, it was present in when I ran the code. Fixed in the example.

from reagent.

dmkolobov avatar dmkolobov commented on May 7, 2024

And to clarify, the accordion-content component renders and disappears whenever the value of expanded? changes, as expected. Regular lifecycle methods are called on it, the special transition group child ones are not.

from reagent.

GetContented avatar GetContented commented on May 7, 2024

I don't understand what you're map-indexing over... it looks like you're trying to map index over a vector with the accordion-component function and the content in it. Very confusing! But... you're probably trying to do something else... this is probably a terrible place to discuss this. I'll be on IRC in a minute if you like.

from reagent.

Reefersleep avatar Reefersleep commented on May 7, 2024

@dmkolobov I'm interested in this as well.

And regarding @GetContented 's question re: map-index, I gather that you're adding individual, unique :keys to your coll in order to satisfy reacts need to distinguish between individual elements in a list. It's a common enough pattern. I do, however, fear that it might interfere with the intent of the :component-will-enter hook and the other ReactTransitionGroup hooks, as I believe that they actually depend on the :key. I can describe it with an example:
A coll of 10 items wrapped in a ReactTransitionGroup with :component-will-leave hooks for each element is mounted. Each element in coll has a :key distinguishing it from all the other elements. The :key is the an integer denoting each item's index in the collection, ie 0, 1, 2... 7, 8, 9.
Now click a button in the UI, intendint to remove the 5th element in the list (with index/:key 4). ReactTransitionGroup now wants to do a diff between the list before the intended removal and after the intended removal so it can determine whether to call lifetime hooks on the item intended for remova. But the diff shows that the item of index 4 has :key 4 after the intended removal, just as before - ReactTransitionGroup is happily unaware that the items in question are actually different, and only look alike to it because they have the same :key, since keys are just allotted by index (with map-index).

This is just me trying to extract info from various experiments I did in trying to get the lifecycle hooks working for reagent, so it's guesswork based on experiments I did a month ago, but I think I did learn that the :key should uniquely identify the item.

This did NOT enable me to get the additional lifecycle hooks working, but I think it was crucial to even get the high level API working properly.

I think, however, that it was @AlexanderWingard who found out that react-transition-group seems to strip any additional lifecycle hooks (and maybe other stuff) from a component before rendering it, though I was unsure from the context whether this was the exact conclusion to be derived from the code. The conclusion doesn't seem to make sense, in that the lifecycle hooks are supported in vanilla react...
https://github.com/reactjs/react-transition-group/blob/v1.1.3/src/TransitionGroup.js#L226

from reagent.

Reefersleep avatar Reefersleep commented on May 7, 2024

Maybe it's a case of reagent's custom-wrapper function not including case entries for ReactTransitionGroup's additional lifecycle hooks? And thus, the functions associated with those hook keywords are called wrongly or not at all?

(defn custom-wrapper [key f]

I haven't tried following the entire flow from reagent (with normal lifecycle hooks) -> react and comparing it to the entire flow through reagent (with additional lifecycle hooks) -> ReactTransitionGroup -> react.

from reagent.

Deraen avatar Deraen commented on May 7, 2024

@Reefersleep If custom-wrapper doesn't return a wrapped function, Reagent will use the provided function as is:

So the function should be called.

from reagent.

AlexanderWingard avatar AlexanderWingard commented on May 7, 2024

Here is my workaround where I set the callback without reagent: https://github.com/AlexanderWingard/reagent-with-transition-group-example

from reagent.

Reefersleep avatar Reefersleep commented on May 7, 2024

@loganpowell that sounds great!
After all of my hardships trying to get ReactTransitionGroup working, I'm personally not very interested in investing the effort to interop with another React library. I can only hope that someone smarter and more persistent than me creates a CLJS wrapper that I can consume :)

from reagent.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.