Hello, I'm trying to get my head around this tool, it looks very promising, specially for collections of elements, but when it comes to animate a single element in & out (specially out) I can't find any example on how it should be implemented. TransitionMotion seems to be meant for with multiple items, I suppose that you can use it just with one, and provably is trivial, but I can't really make it work, does anyone can point me to a plain example with animation in & out for a single object? Thank you very much!
Hi, I can't give you a working example, but I can point you:
<TransitionMotion
styles={
isItemExists ? [{
key: 'someId',
data: {/*custom data (not related to animation) that you need for renderging. it can be component classes*/},
style: {
transform: spring(0, transformSpringConfig),
opacity: spring(1, opacitySpringConfig)
}
}] : []
}
willEnter={this.willEnter}
willLeave={this.willLeave}
>
{(items) => {
const {key, data, style} = items[0];
const {AnotherComponent, props} = data;
return (
<SomeComponent style={{
transform: `translate(${style.transform}%)`,
opacity: style.opacity
}}>
<AnotherComponent {...props} />
</SomeComponent>
);
}}
</TransitionMotion>
willEnter (component apears in DOM) and willLeave (component is being removed from DOM) are the functions that will get an object with fields key, style, data as an argument (the coresponding styles array item. that you specified in TransitionMotion).
The both functions should return new style key values to transition to.
There is only two differences between this functions:
willEnter must return numeric values (e.g. {transform: 50}) and willLeave must return spring values (e.g. {transform: spring(-50, transformSpringConfig)}.willLeave will be called multiple times (this allows you to dynamically change spring configuration based on current style). I have not tested this thing. I always return the same value.Thank you for your answer @SleepWalker, but unfortunately that won't work, the whole key is in
isItemExists ?
, which modifies the array of elements, and tells what need to be animated and when (if I understand it right), on a single element that will initially be an empty array, and when it will be gone as well, therefore next line will break since you can't retrieve style, data, key from an empty object:
const {key, data, style} = items[0]
I just need to animate an overlay fade in/ fade out, maybe this tool is just for complex animations, and should use another one for normal/most common ones ?
Thank you anyway for your support!
By the way my goal is something as simple as this:
willEnter(){
return {opacity : 0}
}
willLeave(){
return {opacity: spring(0)}
}
render(){
return(
<TransitionMotion
styles={
this.state.draggedIn? [{
key: 'dropzoneAnimation',
data: {},
style: { opacity: 1 }
}] : []
}
willEnter={this.willEnter}
willLeave={this.willLeave}
>
{(items) => {
const {key,style} = items[0]
return (
<DropZone style={{opacity:style.opacity}} key={key} />
)
}}
</TransitionMotion>
)
}
@xavibonell and that code does not work? does it have an issue with an empty object? If so, than you can simply check for the items size:
{(items) => {
if (items.length) {
const {key,style} = items[0];
return (
<DropZone style={style} key={key} />
);
}
return null;
}}
Hey @SleepWalker, thank you very much for your follow up! It does work, I just had to return null if the object was missing, silly me!
Anyway, I decided to do my own library to do simple object transitions for my project, this library is clearly too sophisticated for everyday animations, I'm sure that is very powerful when it comes to complex motions though.
Thank you again for your support! It really worked!
Re-opening this because I want this implemented in Motion.
(PR welcome, of course =])
Cannot wait for this @chenglou! I've used react-motion in a project I'm working on here: http://sa.603.nu. I'm trying to fade images on load. Everything is mostly working apart from an issue where images rendered on both the mosaic and artists page flicker before the rest of the images fade in when changing pages. I believe this is because the image has already loaded on the previous page. It can be replicated by navigating to the mosaic page and then going to the artists page. Anyone have any ideas how to beat this?
FYI I fixed the above issue by adding a cachebreaker to my images 馃憤
I'm also struggling to get my mind around how a basic mounting/unmounting animation can be achieved. I think a demo of a modal fading in/out would be very helpful for newcomers to this library.
Exactly @p4bloch need a simple example to do basic mounting or unmounting
I also would like to see simple animation examples, the exemples from the docs are quite complicated, a simple mount, unmount example and a stagger without dynamicaly created elements (i.e stagger opacity on a title, a paragraph and an image for example) would help a lot.
I've been trying to simply animate a mount / unmount component for 6 hours now without success and can't find any demo anywhere.
Tried again for a couple hours but still can't animate an item out, here is a codepen example
And another try... that just won't work... at all.
I think I'm too dumb to use this, I'll probably look into something else.
@Lakston the Child needs to be kept. There's zero magic in the library; it doesn't keep an unmounted child around, dangling in the UI tree.
TransitionMotion pass you the list of currently mounted items in the parameter of the children callback. Here's a working example: https://codepen.io/anon/pen/wzdBoa?editors=0010#0
Edit: I need to put an emphasis that there's zero magic in the library, and no dirty DOM element kept around "hopefully not too long" while waiting for the state of your UI to re-become valid. This also means you need to keep the TransitionMotion wrapper around.
Try that example and ping me if you don't get it!
The discussion in this issue was really useful to me today. I too would love to see single element enter and leave animations in <Motion> one day!
In the meantime, as I was trying to refactor some existing code it got too confusing, so I distilled it down to a very simple example that illustrates all of the possible animations: on mount (with defaultStyles, on transition, on exit (with willLeave) and on enter (with willEnter). I thought my example might be useful to others who use this issue/thread for reference in the future, so here it is: http://codepen.io/jebeck/pen/xgxYbm/
React Motion UI Pack offers this as an option as well as some other common features.
@chenglou I create a EnhancedMotion to handle leave animation using Motion, this is my demo LeaveAnimationUsing Motion
class EnhancedMotion extends React.Component {
constructor(props) {
super(props);
this.state = {
show: true
};
}
componentWillReceiveProps(nextProps) {
const { show } = nextProps;
if(show) {
this.setState({
show: true
});
}
}
onRest2() {
const { show, onRest } = this.props;
if(!show) {
this.setState({
show: false
});
}
onRest && onRest();
}
render() {
// eslint-disable-next-line
const { show, ...restProps } = this.props;
return this.state.show && <Motion {...restProps} onRest = {() => this.onRest2() } />;
}
}
I've managed to create a pretty simple mount/unmount animation with <Motion /> (Demo)
class Example extends React.Component {
constructor() {
super();
this.toggle = this.toggle.bind(this);
this.onRest = this.onRest.bind(this);
this.state = {
open: true,
animating: false,
};
}
toggle() {
this.setState({
open: !this.state.open,
animating: true,
});
}
onRest() {
this.setState({ animating: false });
}
render() {
const { open, animating } = this.state;
return (
<div>
<button onClick={this.toggle}>
Toggle
</button>
{(open || animating) && (
<Motion
defaultStyle={open ? { opacity: 0 } : { opacity: 1 }}
style={open ? { opacity: spring(1) } : { opacity: spring(0) }}
onRest={this.onRest}
>
{(style => (
<div className="box" style={style} />
))}
</Motion>
)}
</div>
);
}
}
I tried to use @zhukmj example and wrap in a component, you can use mount to support mount/unmount behavior.
const Fade = ({
Style, on, mount, children
}) => {
const [animating, setAnimating] = useState(true)
const onRest = () => { setAnimating(false) }
useEffect(() => { setAnimating(true) }, [on])
if (mount) {
if (!on && !animating) {
return null
}
}
return (
<Style
on={on}
onRest={onRest}
>
{children}
</Style>
)
}
Fade.propTypes = {
Style: elementType,
on: bool,
mount: bool,
}
Most helpful comment
Re-opening this because I want this implemented in
Motion.(PR welcome, of course =])