5

Mi chiedevo se qualcuno potesse fornire alcune informazioni su come ottenere un interruttore componente/page animata con React.js.Reagire: Animazione di un interruttore pagina

Quello che mi piacerebbe ottenere è una transizione di componente/pagina come quella su http://www.semplicelabs.com/ - un'intestazione che passa all'opacità e al margine superiore e un contenuto che passa all'opacità.

Quando viene visualizzato un nuovo componente/pagina, il componente/pagina attualmente visualizzata dovrebbe transizione fuori prima il nuovo componente/pagina transizione in ciò che ho finora è un LayoutComponent che rende un componente pagina in un CSSTransitionGroup.:

import React from 'react/addons'; 

export default class LayoutComponent extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { page: '' }; 
    }, 

    setPage(page) { 
    this.setState({ page }); 
    } 

    render() { 
    return (
     <React.addons.CSSTransitionGroup transitionName='page'> 
     {this.state.page} 
     </React.addons.CSSTransitionGroup> 
    ); 
    } 
} 

ho anche due componenti della pagina, FirstPage e SecondPage.

import React from 'react'; 

export default class FirstPage extends React.Component { 
    render() { 
    return (
     <div> 
     <header className='header'> 
      <div className='container'> 
      First Header 
      </div> 
     </header> 
     <div className='content'> 
      <div className='container'> 
      First Content 
      </div> 
     </div> 
     </div> 
    ); 
    } 
} 

Le uniche differenze tra SecondPage codice e FirstPage codice sono i contenuti nei .container div e il nome classi.

Quello che ho tentato di fare è aggiungere una transizione di assenza con la durata .8s e una transizione di immissione con la durata e il ritardo sia .8s. Il problema principale che vedo è che il nuovo componente della pagina viene montato prima che la transizione di partenza di quella precedente sia terminata. Questo è il mio attuale CSS:

.page-enter { 
    background-color: #f2f2f2; 
    transition: background-color .8s linear .8s; 
} 

.page-enter-active { 
    background-color: #f2f1f1; 
} 

.page-leave { 
    background-color: #f2f1f1; 
    transition: background-color .8s linear; 
} 

.page-leave-active { 
    background-color: #f2f2f2; 
} 

.page-enter .header { 
    margin-top: -80px; 
    opacity: 0; 
    transition: opacity .8s ease-in-out .8s; 
    transition: margin-top .8s ease-in-out .8s; 
} 

.page-enter-active .header { 
    margin-top: 0; 
    opacity: 1; 
} 

.page-leave .header { 
    margin-top: 0; 
    opacity: 1; 
    transition: opacity .8s ease-in-out; 
    transition: margin-top .8s ease-in-out; 
} 

.page-leave-active .header { 
    margin-top: -80px; 
    opacity: 0; 
} 

.page-enter .content { 
    opacity: 0; 
    transition: opacity .8s ease-in-out .8s; 
} 

.page-enter-active .content { 
    opacity: 1; 
} 

.page-leave .content { 
    opacity: 1; 
    transition: opacity .8s ease-in-out; 
} 

.page-leave-active .content { 
    opacity: 0; 
} 

So che avrei potuto animare montaggio con transitionAppear={true} iniziale - ma che non aiuta con il problema del nuovo componente che viene montato prima che il vecchio è la transizione fuori.

Questo è un problema che ho lottato con per alcuni giorni e non riesco a trovare una soluzione per.

del codice per giocare con: https://jsfiddle.net/gonsfx/xva2g6oo/

+1

Sei stato in grado di risolvere questo? Sono anche bloccato con questo problema. –

risposta

1

ho aggiunto uno stato alle pagine per salvare un opacity (per l'animazione) e impostarlo su 1 (iniziale = 0) quando il componente ha montaggio con un piccolo ritardo. Quindi ho aggiunto due funzioni a ciascuna pagina.

componentDidMount() { 
    setTimeout(() => { 
     this.setState({ 
      opacity: 1 
     }); 
    }, 20); 
} 

getStyle() { 
    return { opacity: this.state.opacity }; 
} 

poi ho aggiunto un costruttore per fare roba iniziale ....

constructor(props) { 
    super(props); 
    this.state = { opacity: 0 }; 
    this.getStyle = this.getStyle.bind(this); 
    this.componentDidMount = this.componentDidMount.bind(this); 
} 

Here è una demo.

I componenti verranno visualizzati immediatamente sulla pagina, quindi penso che non è possibile fare un'animazione fade out (Almeno, non ho trovato una soluzione per questo).

+0

Questo non svanisce la vecchia pagina prima di mostrare quella nuova. Inoltre, ignora completamente 'CSSTransitionGroup'. Grazie per il tuo impegno, però. – Codepunkt

0

OK. Dopo aver superato molti dei documenti più recenti e obsoleti, sono riuscito a risolverlo. Here is the solution

Fondamentalmente, si occupa router reagiscono solo con l'animazione del contenitore principale. Ma questo significa che usando ReactTransitionGroup, potremmo collegarci al metodo componentWillLeave nel componente in uscita, dove possiamo manipolare i singoli bambini. I componenti per bambini possono anche essere ReactCSSTransitionGroup allo scopo di facilitare la transizione appear.

Quindi potresti non essere in grado di utilizzare solo CSSTransitionGroup, ma un mix di CSSTransitionGroup e TransitionGroup.

Così, cambiando una pagina si animano automaticamente i bambini attraverso il gancio, mentre l'inserimento di una pagina utilizza CSSTransitionGroup per le singole animazioni.

Il setTimeout nella soluzione può sembrare un hack, ma questo è tutto quello che sono stato in grado di fare per ora.