web-dev-qa-db-fra.com

React styled-components fade in / fade out

J'essaye de construire un composant React pour gérer les fondus entrants et sortants. Dans le code suivant, si je passe out comme accessoire au composant, il est affiché comme caché avant l'animation. J'essaie de le faire apparaître par défaut, puis de disparaître lorsque je passe dans l'accessoire out. Quelqu'un voit une solution à ce problème?

import React from 'react';
import styled, { keyframes } from 'styled-components';

const fadeIn = keyframes`
  from {
    transform: scale(.25);
    opacity: 0;
  }

  to {
    transform: scale(1);
    opacity: 1;
  }
`;

const fadeOut = keyframes`
  from {
    transform: scale(1);
    opacity: 0;
  }

  to {
    transform: scale(.25);
    opacity: 1;
  }
`;

const Fade = styled.div`
  ${props => props.out ?
    `display: none;`
   : `display: inline-block;`
   }
  animation: ${props => props.out ? fadeOut : fadeIn} 1s linear infinite;
`;

function App() {
  return (
    <div>
      <Fade>&lt;????test&gt;</Fade>
    </div>
  );
}

export default App;

exemple d'exécution de WebpackBin

13
Elliot

Le problème avec votre code est que vous définissez la propriété d'affichage sur aucune lorsque props.out est vrai. C'est pourquoi vous ne voyez aucune animation, car avant même de pouvoir démarrer, vous avez déjà masqué le composant!

La façon de faire une animation en fondu est d'utiliser à la place la propriété de visibilité et de la transposer pendant la même durée que l'animation. (voir cette ancienne SO )

Quelque chose comme ça devrait résoudre vos problèmes:

const Fade = styled.default.div`
  display: inline-block;
  visibility: ${props => props.out ? 'hidden' : 'visible'};
  animation: ${props => props.out ? fadeOut : fadeIn} 1s linear;
  transition: visibility 1s linear;
`;
const fadeIn = styled.keyframes`
  from {
    transform: scale(.25);
    opacity: 0;
  }

  to {
    transform: scale(1);
    opacity: 1;
  }
`;

const fadeOut = styled.keyframes`
  from {
    transform: scale(1);
    opacity: 1;
  }

  to {
    transform: scale(.25);
    opacity: 0;
  }
`;

const Fade = styled.default.div`
  display: inline-block;
  visibility: ${props => props.out ? 'hidden' : 'visible'};
  animation: ${props => props.out ? fadeOut : fadeIn} 1s linear;
  transition: visibility 1s linear;
`;

class App extends React.Component {
  constructor() {
    super()
    this.state = {
      visible: true,
    }
  }

  componentDidMount() {
    setTimeout(() => {
      this.setState({
        visible: false,
      })
    }, 1000)
  }

  render() {
    return (
      <div>
        <Fade out={!this.state.visible}>&lt;????test&gt;</Fade>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('root')
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<script src="https://unpkg.com/styled-components/dist/styled-components.min.js"></script>

<div id="root" />

Remarque: votre animation fadeOut est également passée de 0 à 1 opacité, au lieu de l'inverse. J'ai également corrigé cela dans l'extrait.

15
mxstbr