3

I have a component that switches some content and the animation of the content depending on the side it is switching it from:

import React, { Component } from "react";

class Skills extends Component {
  constructor(props) {
    super(props);

    this.state = {
      shownSkill: 0,
      fallIn: true,
      slideUp: false
    };
  }

  getPreviousSkill = () => {
    const { shownSkill } = this.state;
    const newSkill = shownSkill < 1 ? 3 : shownSkill - 1;
    this.updateShownSkill(newSkill, false);
  };

  getNextSkill = () => {
    const { shownSkill } = this.state;
    const newSkill = shownSkill > 2 ? 0 : shownSkill + 1;
    this.updateShownSkill(newSkill, true);
  };

  updateShownSkill = (skillIndex, fallIn) => {
    this.setState({
      shownSkill: skillIndex,
      fallIn: fallIn,
      slideUp: !fallIn
    });
  };

  getSkillData = () => {
    const { skills } = this.props;
    const { shownSkill } = this.state;
    return skills[shownSkill];
  };

  render() {
    const { name, skill, description } = this.getSkillData();
    const { shownSkill, slideUp } = this.state;
    const { skills } = this.props;
    return (
      <div className="route-container skills">
        <div className="skills-content-container">
          {slideUp ? (
            <div className="skills-right-content slide-up">
              <div className="subtitle">{name}</div>
              {description.map((p, i) => (
                <div className="text" key={i}>
                  {p}
                </div>
              ))}
            </div>
          ) : (
            <div className="skills-right-content
            fall-in">
              <div className="subtitle">{name}</div>
              {description.map((p, i) => (
                <div className="text" key={i}>
                  {p}
                </div>
              ))}
            </div>
          )}
        </div>
      </div>
    );
  }
}

export default Skills;

Then I am animating the .fall-in class with css:

@keyframes fall-in {
  0% {
    margin-top: -600px;
  }
  100% {
    margin-top: 0;
  }
}

.fall-in {
  animation-name: fall-in;
  animation-duration: 0.5s;
  animation-timing-function: linear;
  animation-iteration-count: 1;
}

I would like this animation to trigger once every time the content of the .subtitle and .text divs changes, regardless of whether or not the animation changed.

This example will only trigger the animation the first time the css class is added.

Miha Šušteršič
  • 9,742
  • 25
  • 92
  • 163
  • From your question, it sounds like react-transition-group component can handle your animations. https://github.com/reactjs/react-transition-group/tree/v1-stable. – SteveB Feb 18 '18 at 17:36
  • I guess...But I am building a webpage with react-static and would like to keep the bundle size as small as possible, so I'm looking for another solution - basically trying to figure out a hack how to make react re-render the DOM – Miha Šušteršič Feb 18 '18 at 17:40
  • If your goal is to have React re-render the DOM, you can change add or remove a className or something else via setState to force a re-render on change. Are the .subtitle and .text divs coming from state or is the user entering it? I can't picture what your application is doing but it sounds interesting. – SteveB Feb 18 '18 at 17:44
  • Basically they are coming from a CMS that react-static passes as props. It's a portfolio - the component is switching between the different CV skills, and animating the text. The thing is, that even though the content of the div (`subtitle`, `text`) is changing, the DOM node itself does not re-render, so the class only gets applied once (not triggering the animation) – Miha Šušteršič Feb 18 '18 at 17:49
  • Have you checked out https://stackoverflow.com/questions/32414308/updating-state-on-props-change-in-react-form which discusses using componentWillReceiveProps(nextProps) to update your state based on props changing? It's an old post and may be outdated, but it seems similar to your needs. – SteveB Feb 18 '18 at 18:01
  • Keys are a great way to force-rerender and apply a keyframe animation again. If you want to change on every content change you can set your key to the content or number of changes. If you provide a working sandbox, could probably help you out more. – Shalanah Dec 07 '21 at 23:38

1 Answers1

0

Hey maybe you want to give a try on my OSS.

https://github.com/bluebill1049/react-simple-animate

I think it does what you want above, maybe worth to give it a try?

import Animate from 'react-simple-img';
import React from 'react';

export default ({ready}) => {
   return <Animate startAnimation={ready} startStyle={{
       marginTop: '-600px',
   }} endStyle={{
       marginTop: '0',
   }}>
       <YourComponent />
   </Animate>
};
Bill
  • 17,872
  • 19
  • 83
  • 131