2016-10-13 5 views
5

Ich lerne React + Redux und ich verstehe nicht die richtige Art, die Animationen zu machen. Lass uns mit einem Beispiel sprechen:Redux/Flux (mit ReactJS) und Animation

Zum Beispiel habe ich eine Liste und möchte Elemente auf Klick entfernen. Das ist super einfach, wenn ich dort keine Animationseffekte habe: Versand REMOVE_ITEM Aktion auf Klick, Reducer entfernt den Artikel aus dem Store und reagiert neu rendert HTML.

Fügen Sie eine Animation zum Löschen der Werbebuchung beim Klicken hinzu. Also, wenn Benutzer auf ein Element klickt, möchte ich einen fantastischen Effekt der Werbebuchung entfernen und ... wie? ich von mehreren Möglichkeiten denken kann, wie es geht:

1) Auf Klick ich REMOVE_ITEM Aktion versenden, dann markieren Minderer ein Element als goingToBeDeleted in Store, dann reagieren, dieses Element mit einer Klasse von .fancy-dissolve-animation macht und ich führe einen Timer um die zweite Aktion zu versenden REMOVE_ITEM_COMPLETED. Ich mag diese Idee nicht, weil es immer noch unklar ist, wie man hier JS-Animationen hinzufügt (zum Beispiel mit TweenMax) und ich einen JS-Timer zum Rendern verwende, wenn die CSS-Animation endet. Klingt nicht gut.

2) Ich verschicke ITEM_REMOVE_PROGRESS Aktionen mit einem Intervall von ~ 30ms, und speichern enthält einige "Wert", der den aktuellen Stand der Animation darstellt. Ich mag es auch nicht, da es mich zwingt, den Laden ~ 120 mal für ~ 2 Sekunden Animation zu kopieren (sagen wir, ich möchte glatte 60 fps Animation) und das ist einfach eine Verschwendung von Speicher.

3) Erstellen Sie eine Animation und senden Sie REMOVE_ITEM erst nach dem Ende der Animation. Das ist die am besten geeignete Art und Weise, die ich mir vorstellen kann, aber trotzdem möchte ich, dass die Dinge im Speicher geändert werden, direkt nachdem der Benutzer die Aktion ausgeführt hat. Zum Beispiel kann die Animation länger als ein paar Sekunden dauern und REMOVE_ITEM könnte mit einem Backend synchronisiert werden - es gibt keinen Grund, die Beendigung der Animation auf einen Backend-API-Aufruf zu warten.

Danke fürs Lesen - irgendwelche Vorschläge?

+0

Animationen, die keinen Dateneinfluss haben, sollten außerhalb des Redux-Speichers liegen. –

+0

@MaciejSikora Ja, stimme völlig zu - so soll es sein. Aber ich habe immer noch keine Ahnung, wie ich das erreichen kann. :( – shlajin

Antwort

4

React hat eine großartige Lösung für dieses Problem in der Helper-Klasse ReactCSSTransitionGroup (siehe https://facebook.github.io/react/docs/animation.html). Mit dieser Option kümmert sich React um Sie, indem der DOM-Status für das untergeordnete Element beim letzten Rendern beibehalten wird. Sie verpacken Ihre Objekte einfach in ein ReactCSSTransitionGroup-Objekt.Diese verfolgt ihre untergeordneten Elemente. Wenn sie mit einem untergeordneten Element gerendert wird, wird das Rendern ohne das untergeordnete Element mit dem untergeordneten Element gerendert. Stattdessen wird dem untergeordneten Element eine CSS-Klasse hinzugefügt (mit der Sie eine CSS-Animation auslösen können) Sie können einfach CSS-Übergänge zur Vereinfachung verwenden). Nach einer Zeitüberschreitung (konfiguriert als eine an ReactCSSTransitionGroup übergebene Requisite) wird sie erneut gerendert, wobei das Kind aus dem DOM entfernt wird.

Um ReactCSSTransitionGroup verwenden zu können, müssen Sie npm react-addons-css-transition-group installieren und dann 'react-addons-css-transition-group' anfordern/importieren. Die Animationsdokumente geben detailliertere Informationen.

Eine Sache zu erinnern - stellen Sie sicher, dass die Kinder einzigartige, unveränderliche Schlüssel haben. Wenn Sie nur den Index als Schlüssel verwenden, wird er sich falsch verhalten.

+0

Großartig, das ist näher an dem, wonach ich suche. Werde es bald versuchen, vielen Dank! – shlajin

+0

Danke, genau was ich brauche! Sorry für die späte Antwort obwohl: P – shlajin

2

Sofortige Aktionen sind problematisch in Redux, die Zustand speichert, also wenn wir Aktion senden und es Geschäft ändern wird dann diese Änderung im Speicher in den nächsten Zuständen verfügbar, so können wir Situation haben, wo Animation immer und immer wieder da im Laden zeigt Dieser Parameter wurde festgelegt.

Meine Lösung für redux sofortige Aktionen ist es, einige id wie (Action-Beispiel-Code) hinzufügen:

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

Next in Komponente, die Animationen letzte Animation ID speichern läuft und wenn ihr Spiel Animation nicht tun. Ich benutze Komponente Zustand, so zum Beispiel (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 

} 

Dank id können wir nur eine Aktion ohne Aktionen haben, die den Staat sind umgekehrt wird. Das Umkehren von Aktionen nach dem Timeout kann zu Problemen führen, da, wenn eine andere Aktion (die mit der Komponente verbunden ist) vor einer umgekehrten Aktion gesendet wird, die Animation erneut beginnen kann.

Nachteile von mir vorgeschlagenen Ansatz sind, dass Animationsdaten im Zustand existiert, sondern existiert auch Animation ID, die uns Informationen darüber geben. So können wir sagen, dass der Laden die zuletzt versandte Animation speichert.

+0

Danke für die Lösung. Und wer ist verantwortlich für die Versendung "ANIMATION_FINISHED" Aktion? Die Animation selbst? – shlajin

+0

In dieser Lösung brauchen Sie keine solche Aktion. Ich habe es im Text über umgekehrte Aktionen beschrieben. Es ist sofortige Aktion mit ID, So bleibt es im Zustand. –

+0

Oh, ich sehe, was Sie jetzt meinen. Leider kann ich immer noch nicht klar sagen, wie dies mit einer Löschaktion helfen kann. Mit Ihrer Lösung würde ich Elemente als "entfernt" markieren + Animationen hinzufügen ID: Während dies funktionieren könnte, ist es immer noch nicht sehr gut, da ich Gegenstände im Laden entfernt haben :( – shlajin