web-dev-qa-db-fra.com

Utilisation de ReactCSSTransitionGroup avec un composant stylé

J'utilise styled-components au lieu de la manière traditionnelle de css. Mais je ne sais pas comment cela peut fonctionner avec ReactCSSTransitionGroup .

En règle générale, ReactCSSTransitionGroup recherche certains noms de classe dans la ressource css, puis les applique à un composant tout au long de son cycle de vie. Cependant, avec styled-components, il n'y a pas de nom de classe, les styles sont appliqués directement aux composants.

Je sais que je peux choisir de ne pas utiliser ReactCSSTransitionGroup car les deux techniques ne semblent pas compatibles. Mais lorsque je n'utilise que styled-components, il semble que je ne puisse pas restituer d'animation lorsqu'un composant est démonté - c'est du css pur, il est impossible d'accéder au cycle de vie du composant.

Toute aide ou recommandation est appréciée.

13
Stanley Luo

Je ne voulais pas utiliser injectGlobal comme suggéré dans une autre réponse car je devais rendre les transitions différentes par composant.

Cela se révèle être assez facile - imbriquer les classes de transition dans le style du composant:

import React from "react";
import CSSTransitionGroup from 'react-transition-group/CSSTransitionGroup';
import styled from 'styled-components';

export default () => {
    const appearDuration = 500;
    const transitionName = `example`;

    const Container = styled.section`
        font-size: 1.5em;
        padding: 0;
        margin: 0;

        &.${transitionName}-appear {
            opacity: 0.01;
        }

        &.${transitionName}-appear-active {
            opacity: 1;
            transition: opacity ${appearDuration}ms ease-out;
        }`;


    return (
        <CSSTransitionGroup
            transitionName={transitionName}
            transitionAppear={true}
            transitionAppearTimeout={appearDuration}>
            <Container>
                This will have the appear transition applied!
            </Container>
        </CSSTransitionGroup>
    );
};

Notez que j'utilise la plus récente CSSTransitionGroup, plutôt que ReactCSSTransitionGroup, mais cela devrait également fonctionner pour cela.

20
Mike Goatly

L'approche de Mike Goatly est géniale, mais j'ai dû faire de petits changements pour que cela fonctionne. J'ai changé les accessoires du <CSSTransition> et utilisé une fonction comme son enfant.

Voir ci-dessous pour un exemple de composant dont l'entrée et la sortie sont fondues en fonction d'un changement d'état:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import { CSSTransition } from "react-transition-group";
import styled from "styled-components";

const Box = styled.div`
  width: 300px;
  height: 300px;
  background: red;
  transition: opacity 0.3s;

  // enter from
  &.fade-enter {
    opacity: 0;
  }

  // enter to
  &.fade-enter-active {
    opacity: 1;
  }

  // exit from
  &.fade-exit {
    opacity: 1;
  }

  // exit to 
  &.fade-exit-active {
    opacity: 0;
  }
}`;

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      active: true
    };

    setInterval(() => this.setState({ active: !this.state.active }), 1000);
  }

  render() {
    return (
      <CSSTransition
        in={this.state.active}
        classNames="fade"
        timeout={300}
        unmountOnExit
      >
        {() => <Box />}
      </CSSTransition>
    );
  }
}
2
Daniel Apt

Utilisez la méthode d'assistance injectGlobal() styled-Component où votre application React est démarrée. Avec cette méthode, vous pouvez appeler n'importe quel sélecteur CSS comme si vous utilisiez du CSS conventionnel.

Commencez par créer un fichier JS exportant un littéral de modèle avec votre CSS pour la syntaxe react-transition-group (veuillez ne pas utiliser la nouvelle version 2.1 des noms de classe):

globalCss.js

const globalCss = `
    .transition-classes {
        /* The double class name is to add more specifity */
        /* so that this CSS has preference over the component one. */
        /* Try removing it, you may not need it if properties don't collide */
        /* https://www.styled-components.com/docs/advanced#issues-with-specificity */

        &-enter&-enter {
        }

        &-enter&-enter-active {
        }

        &-exit&-exit {
        }

        &-exit&-exit-active {
        }
    }
`;

export default globalCss;

Puis sur votre fichier de point d’entrée:

index.jsx

import { injectGlobal } from "styled-components";
import globalCss from "./globalCss.js";

injectGlobal`${ globalCss }`; // <-- This will do the trick

ReactDOM.render(
    <Provider store={ Store } >
        <HashRouter >
            <Route path="/" component={ Component1 } />
            <Route path="/" component={ Component2 } />
        </HashRouter>
    </Provider>,
    document.getElementsByClassName("react-app")[0]
);

Toutefois, si vous utilisez uniquement CSS/SASS/Less pour écrire les classes pour le react-trasition-group même lorsque vous utilisez des composants stylés, cela fonctionne également bien.

2
AxeEffect

Vous pouvez utiliser le sélecteur de variable css dans styled-components. Comme ça:

const Animation = styled(ReactCSSTransitionGroup)`
  ${({ transitionName }) => `.${transitionName}-enter`} {
    opacity: 0;
  }

  ${({transitionName}) => `.${transitionName}-leave`} {
    opacity: 1;
  }
`

const animationID = 'some-hashed-text'

const AnimationComponent = props => (
  <Animation
    transitionName={animationID}
    transitionEnterTimeout={0.1}
    transitionLeaveTimeout={2000}
  >
    <div>some content</div>
  </Animation>
)

1
Chiahao Lin