Closed zendevil closed 4 years ago
Not that this is any help, but i would love for someone to weigh in on this. Furthermore, zendevil, i'm impressed you got as far as importing the framer-motion library. I've tried all day to get framer-motion merely required, to no avail. I'm using shadow-cljs, but i can't think how that matters. (Besides, i'm so happy with shadow-cljs, i'd sooner give up on a promising new npm than shift from shadow-cljs as my build tool.)
The opacity animation from 0 to 1 is triggered on click, and not on page load. The component isn't being focused the first time. It focuses when the window is refocused and thus the animation triggers. @Deraen reagent isn't focusing the framer motion motion.div object automatically on page load. In the same situation react would.
Framer Motion states:
https://www.framer.com/api/motion/animation/#mount-animations " Mount animations
When a component mounts, it'll automatically animate to the values in animate if they're different from those defined in style or initial. You can set the initial prop to false to use the value in animate as the component's mounted state to disable mount animations.
<motion.div animate={{ x: 100 }} initial={false} /> This will also work with server-side rendering."
The component is mounted:
<div class="flex flex-col items-center border-5" style="opacity: 0;"></div>
And has opacity 0. The mounted div is stuck at :initial.
-- EDIT -- The animation isn't triggered when a click is simulated by adding these to the :> div map:
{:ref simulate-click
:on-click #(prn "element clicked!")}
where simulate-click is:
(defn simulate-click [e]
(prn "event is " e)
(-> e .click)
)
-- EDIT --
I get the following error in the console when using framer motion like this:
(defn my-component []
(fn [] [:> div "Foo"]))
TypeError: lastCallbackNode is not a function. (In 'lastCallbackNode()', 'lastCallbackNode' is 1)
flushFirstCallback — module$node_modules$scheduler$cjs$scheduler_development.js:2:479
flushWork — module$node_modules$scheduler$cjs$scheduler_development.js:6:147
(anonymous function) — module$node_modules$scheduler$cjs$scheduler_development.js:12:365
flushFirstCallback — module$node_modules$scheduler$cjs$scheduler_development.js:2:479
this is the my-component function in the compiled version:
myapp.mycomponent.mycomponent = (function myapp$mycomponent$mycomponent(){
return (function (){
return new cljs.core.PersistentVector(null, 3, 5, cljs.core.PersistentVector.EMPTY_NODE, [new cljs.core.Keyword(null,">",">",-555517146),myapp.component.div,"foo"], null);
});
I tested framer-motion with Reagent and toggling a animated div with opacity changes works here: https://github.com/reagent-project/reagent/compare/framer-motion-example
@Deraen it does work for me with reagent 0.10.0 and react/react-dom 16.8.6, but not with reagent 1.0.0-alpha2 and react/react-dom 16.13.0. Your test uses shadow-cljs 2.8.93. I'm using 2.9.2 in both cases. It works when downgrading to 2.8.93.
What doesn't work?
I've updated deps and the example still works fine.
I was able to make a similar use case as you show in the new example work, but there a some framer-motion use cases where we seem to need to use a react hook from framer-motion. A good example is from Framer Motion Example 35 Swipe to Delete (CodeSandbox)
In particular around the use of the Animation Controls:
const controls = useAnimation();
...
controls.start({ x: 0, opacity: 1, transition: { duration: 0.5 } });
I get the error:
Uncaught Invariant Violation: Invalid hook call. Hooks can only be called inside of the body of a function component
This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
...
My framer-motion/react/reagent fu is not up to figuring out how to do any of the above in the reagent context.
This library is pretty amazing IMHO, so it would be fabulous to use all its abilities in Reagent apps.
I've added an example using useAnimation
and useEffect
hooks.
I'm using the framer-motion library to animate a div mount
This is what I have:
And a boolean
show-my-component?
is changed from false to true when I click on a button (I'm using re-frame for managing the booleanshow-my-component?
but have simplified the code here):But the component doesn't show immediately when clicking the button when using :>div, although it does when using a regular :div, but in the latter case of course there's no animation
when using
:> div
, I have to re-focus or click somewhere on the webpage for my-component to showHow do I fix this issue?