-
Notifications
You must be signed in to change notification settings - Fork 47.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Animating when adding/removing a single component #226
Comments
Here's a thought: Right now, the when any props of a
Right now, the default behavior is to simply carry out this plan in the most efficient way that we can. What if, you could tell these native components that you want to handle the insertions/removals/moves in a very particular way (that may include animation). Something like:
Where
What's interesting is that not only are child instances added/moved/removed, but also updated. We need an API that allows controlling when/how these updates occur throughout the process of creating/destroying/moving. You may wish to update before you move existing children/add new ones, or you may wish to update them after all the adding/movement is complete. It seems like the best strategy is to make sure that the lowest level hooks are exposed, so that no one ever feels completely trapped by not being able to perform their particular animation feature. Then, on top of that, we can build sugar that does some very common things, such as:
|
I'm also really hyped up for animation, here's the old issue: #161 I like @jordwalke's idea. This also allows for graceful degradation. And the best part is it's totally unobstructive and could be used as a drop-in mixin. I'm kind of drooling at the possibilities lol. One thing I'm worried about is the parent/siblings' expectation of what should/should not happen during/after the animation, but I'm sure it can be worked out. |
Oops, I forgot about your earlier issue! Agree that more flexibility is always better, was just brainstorming some possible new APIs – we want simple things to be easy. |
A couple of other features that I've heard requests for (I think this hits on @chenglou's comment):
Another completely different direction to take, which doesn't really address animating child components but focuses more on property values: Pete Hunt's work on animatable state transitions:
Which would just call setState several times, throttling to hit the We've also talked about being able to implement |
I think |
Oh I guess TransitionGroup handles #227 but not this without restructuring a bit... |
Actually I think this is pretty reasonable with TransitionGroup. |
In the future when we have x:frag it'll be Even Better™. |
Is this actually possible? I've been messing around with it, but can only seem to get it to work with an array of children. |
Never mind, I was wrong! For future problem havers, you need to remove the elements inside the CSSTransitionGroup, not the CSSTransitionGroup itself :) |
Was there ever a direct resolution to this ticket (it's possible I've missed a few things in the comments here)? To recap, it's clear how you can elegantly cause enter animations by setting state from known properties in React.createClass({
getDefaultProps: function() {
return { items: [1, 2, 3] }
},
getInitialState: function() {
return { items : [] }
},
componentWillMount: function() {
this.setState({ items: this.props.items })
},
render: function() {
return (
<ReactCSSTransitionGroup transitionName="item">
{this.state.items.map(function(item, index) {
return <span key={index}>{item}</span>
})
</ReactCSSTransitionGroup>
)
},
componentWillUnmount: function() {
// Obviously broken.
this.setState({ items: [] })
}
}) It's been a frustrating exercise trying to accomplish this effect in a more complex application (in my case, one using a router library and Flux pattern) where there's little or not control at components one level up the hierarchy from those wishing to do animations. If it was possible to capture and then perform leave animations as illustrated here, I'd be able to cut a huge amount of complexity. PS, please forgive the lack of semicolons—I write a lot of Scala these days. |
@michaelahlers I have a working wrapper (animation library-agnostic, mostly) here. It's a bit messy right now but once I find some more free time I'll pull it out. See chenglou/react-tween-state#15 as well. (This sure brings back memories =)) |
@chenglou, leave it to me to dig up nostalgia fuel for you. 😏 Reading your samples there is kind of funny; I was contemplating—even as I wrote my comment—about how enter and exit transitions are inadequate for a lot of animation use cases, and struggling to make them work in this framework might result in isolated, short-term gains for big-picture, long-term losses. Your work definitely looks several steps ahead! State Stream looks incredibly powerful and—with a functional programming background—equally intuitive. Combined with Tween State, I can imagine a lot of sophistication that can't be accomplished purely in CSS. That said, it looks like @irvinebroque and I are in the same boat: needing a good baby step that adds exit animation classes with node removal only after CSS animations complete. |
Eh sorry, state-stream is unrelated. The wrapper should mostly work in conjunction with anything else, including a simple |
You may have lost me a bit. |
A good way to animate a removal is delaying it. for instance, when you call the delete function, it updates the state, saying the element x will be removed. then, it sets a timeout or make a AJAX request. Meanwhile, the component will recive the signal and will animate itself. Another way is never remove the element. it will be always there, but the visible state will be changed. Material-UI uses this, for instance. |
This is how we handled it:
Then, for example, if you want to:
, then you can do it like that: const MyOpeningComponent = ({ initialModalOpen = false }) => {
const [mountModal, setMountModal] = useState(initialModalOpen);
const [openModal, setOpenModal] = useState(initialModalOpen);
const handleOpen = useCallback(() => {
setMountOverlay(true);
setOpenOverlay(true);
}, []);
const handleClose = useCallback(() => {
setOpenOverlay(false);
}, []);
const handleCloseTransitionEnd = useCallback(() => {
if (!openModal) {
setMountModal(false);
}
}, [openModal]);
return (
<>
<button onClick={handleOpen}>Open modal</button>
{(mountModal || openModal) && (
<MyModal
open={openModal}
onClose={handleClose}
onCloseTransitionEnd={handleCloseTransitionEnd}
/>
)}
</>
);
}; |
Improve performance by mutating the children array
It's useful to be able to animate the appearance and disappearance of a particular component.
It's possible to animate entrances without too much trouble by hand, using componentDidMount but exits are harder since elements disappear immediately after componentWillUnmount and don't give the animation time to finish.
What can we add to React to make this easy?
(See also #227.)
The text was updated successfully, but these errors were encountered: