Redux / Flux (with ReactJS) and animation

I am learning React + Redux, and I do not understand the correct way to animate. Let's talk on an example:

For example, I have a list, and I would like to remove items in a click. It is very simple if I do not have animation effects: send a REMOVE_ITEM action on a click, the reducer will remove the item from the store and respond to re-renders html.

Add an add position delete animation on click. Thus, when the user clicks on an item, I want to launch a fancy effect of deleting a position and ... how? I can come up with several ways to do this:

1) In a click, I submit the REMOVE_ITEM action, then the reducer marks the item as goingToBeDeleted in the Store, and then responds to the visualization of this element with the .fancy-dissolve-animation class, and I start the timer to dispatch the second REMOVE_ITEM_COMPLETED action. I do not like this idea because it is not yet clear how to add JS animation here (for example, with TweenMax ), and I start a JS timer to re-render when the CSS animation finishes. That sounds good.

2) I send ITEM_REMOVE_PROGRESS actions with an interval of ~ 30 ms, and some "value" is stored in the repository, which represents the current state of the animation. I don’t like it either, since I need to copy the repository ~ 120 times in ~ 2 seconds of animation (let's say I want a smooth animation of 60 frames per second), and this is just a waste of memory.

3) Make an animation and send REMOVE_ITEM only after the animation finishes. This is the most suitable way that I can think of, but still I would like everything to be changed in the store right after the user has completed the action. For example, an animation can take longer than a few seconds, and REMOVE_ITEM can synchronize with the backend - there is no reason to wait for the animation to finish to make a call to the backend API.

Thanks for reading - any suggestions?

+5
source share
2 answers

React has a great solution to this problem in the ReactCSSTransitionGroup helper class (see https://facebook.imtqy.com/react/docs/animation.html ). With this option, React will take care of this for you, preserving the DOM state for the child, as was the case with the last rendering. You simply transfer your objects to the ReactCSSTransitionGroup object. This keeps track of its children, and when it is rendered with a child removed, instead of rendering without a child, it displays with a child, but adds a CSS class to the child (which you can use to trigger CSS animations or you can just use CSS transitions for simplicity) . Then, after a timeout (configured as prop passed to ReactCSSTransitionGroup), it will re-render again, and the child is removed from the DOM.

To use ReactCSSTransitionGroup, you need to install npm install-addons-css-transition-group and then require / import "add-addons-css-transition-group". Animation documents contain more detailed information.

One thing to remember is to make sure children have unique, immutable keys. Just using an index, as the key will lead to a malfunction.

+4
source

Instant actions are problematic in reducing, which saves state, so if we submit the action and it changes the store, then this change in the store will be available in the following states, so we may have a situation where the animation is displayed again and again, because in A store such option has been set.

My solution for reducex instant actions is to add some identifier (example code example):

 { type:"SOME_ANIMATION", id: new Date().getTime() //we get timestamp of animation init } 

Further, in the component that starts the animation, it saves the last animation identifier, and if it matches, it does not make the animation. I use the state of the component, for example, (Component Code):

 componentDidUpdate (){ if (this.lastAnimationId===this.props.animation.id) return; //the same animation id so do not do anything //here setState or do animation because it is new one this.lastAnimationId=this.props.animation.id; //here set new id of last abnimation } 

Thanks id , we can only have one action without actions that change state. Reverse actions after a timeout can cause problems, because if another action (which is associated with the component) is sent before the reverse action, then the animation may start again.

The disadvantages of my approach are that the animation data exists in the state, but there is also an animation identifier that gives us information about this. Thus, we can say that the store saves the last sent animation.

+2
source

Source: https://habr.com/ru/post/1258133/


All Articles