Comments (23)
https://github.com/reagent-project/reagent-cookbook/tree/master/recipes/ReactCSSTransitionGroup
from reagent.
@dmkolobov
I'm interested, did you ever get this to work?
from reagent.
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.
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.
New issue should be created about not being able to use ReactTransitionGroup.
from reagent.
On a related note, I don't see any animation on the TODO example, even if the animation CSS is there.
from reagent.
This would be pretty awesome. I wonder if there has been any further movement on this?
from reagent.
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.
@gadfly361 might be an idea to create a recipe for this :)
from reagent.
@yogthos Agreed!
@jcreedcmu Would you be interested in creating a reagent-cookbook recipe for this?
from reagent.
@yogthos Just revisited this and should have recipe in the next couple of days.
from reagent.
@gadfly361 fantastic :)
from reagent.
<3
from reagent.
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.
@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.
Whoops, @JulianLeviston forgot to add in the example, it was present in when I ran the code. Fixed in the example.
from reagent.
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.
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.
@dmkolobov I'm interested in this as well.
And regarding @GetContented 's question re: map-index
, I gather that you're adding individual, unique :key
s to your coll in order to satisfy react
s 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.
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?
reagent/src/reagent/impl/component.cljs
Line 147 in d76eaba
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.
@Reefersleep If custom-wrapper
doesn't return a wrapped function, Reagent will use the provided function as is:
reagent/src/reagent/impl/component.cljs
Lines 205 to 208 in d76eaba
reagent/src/reagent/impl/component.cljs
Line 242 in d76eaba
reagent/src/reagent/impl/component.cljs
Line 261 in d76eaba
reagent/src/reagent/impl/component.cljs
Line 267 in d76eaba
So the function should be called.
from reagent.
Here is my workaround where I set the callback without reagent: https://github.com/AlexanderWingard/reagent-with-transition-group-example
from reagent.
@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)
- Bad react key warning when using false as key
- examples/material-ui not work HOT 1
- examples/material-ui not work HOT 1
- Docs on “Changed?” inaccurate? HOT 5
- React 18 does not live reload with Shadow-CLJS in non-trivial projects HOT 5
- Prop types
- `TypeError` when using function components with `r/create-class` with `dom.server/render-to-string`
- ReactDOM.render is no longer supported in React 18. Use createRoot instead. HOT 2
- shadow-cljs emits a warning when using with-let HOT 4
- Korean input broken on :input and :textarea HOT 1
- Update docs? HOT 1
- MUI ThemeProvider not working HOT 1
- @@ -62,6 +62,45 @@ class _Config { } } // eslint-disable-next-line valid-jsdoc /** * fetch problem title, level via solved.ac api * @see {@link https://solvedac.github.io/unofficial-documentation/#/operations/getProblemByIdArray} * @param {string[]} pids - list of problem id (up to 100) * @param { ({ problemId, titleKo, level }) => void } callback */ function fetchProblemsFromSolvedAc(pids, callback) { const query = encodeURIComponent(pids.join(',')); console.log(`https://solved.ac/api/v3/problem/lookup?problemIds=${query}`); fetch(`https://solved.ac/api/v3/problem/lookup?problemIds=${query}`) .then((res) => { console.log('fetchProblemsFromSolvedAc', res); return res; }) .then((res) => res.json()) .then(callback) .catch(() => callback(null)); }
- Readme says npm i or add deps to .edn but (in my case at least) needed both HOT 1
- Any interest in being able to replace `react/createElement` with a custom function? HOT 7
- The cursor disappears at the end of a controlled input on Chrome
- Reusable components following HTML semantics of Opional Attributes and Variadic Children HOT 3
- Controlled input loses cursor under ShadowRoot in React 18 HOT 3
- snake_case mentioned instead kebab-case in documentation of create-class function.
- Class name composition is harder than it needs to be
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from reagent.