1

I'm trying to figure out how to trigger the animation only once at the startup of the app..

Currently I'm facing the problem that If I switch to another view(another component, using React-router-dom) and then switch back to Home component, animation fires again. I'm using react-spring for this animation.

I just want to make that animation fire only once on start of the app. Not after every switch to Home. Is there any config in React-spring, or do you guys know how to prevent this? I can't really find anything helpful.

Setting the animation

//State for animation
const [showGameOptions, setShowGameOptions] = useState(true);

//Starting animation
const gameOptionsTransitions = useTransition(showGameOptions, null, {
  from: { opacity: 0, transform: 'translateY(200px)' },
  enter: { opacity: 1, transform: 'translateY(0)' },
  leave: { opacity: 0, transform: 'translateY(200px)' },
});

I've set the initial state to true, because I want to trigger that animation on start. To this part it works nice.

Home Component's return()

<div className="homeScreen">
  <h1>Tic Tac Toe</h1>
  <p>Select game mode</p>
  {gameOptionsTransitions.map(
    ({ item, key, props }) =>
      item && (
        <animated.div key={key} style={props}>
          <Link to="/play" className="setGameMode-btn" onClick={playPlayerVsComputer}>
            Player vs. Computer
          </Link>

          <Link to="/play" className="setGameMode-btn" onClick={playPlayerVsPlayer}>
            Player vs. Player
          </Link>
        </animated.div>
      ),
  )}
</div>
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Pinncik
  • 321
  • 3
  • 14
  • You can use browser history to make sure that you have already visited the home page. Did you try that out? You are already using react-router-dom right. – Dushan Ranasinghage Nov 05 '20 at 14:23
  • No I didn't tried that. I'm kinda new to this so that's why I'm asking here for help. Is that difficult with that browser-history? – Pinncik Nov 05 '20 at 14:27
  • You can use `useEffect` to fire the animation when you component is rendered. But the problem is your animation will fire again and again when you visit to that component. This is what happens right now. Am I right? – Dushan Ranasinghage Nov 05 '20 at 14:35
  • Yes . You are right . This useEffect approach I’ve tried before posting this question :/ – Pinncik Nov 05 '20 at 14:46

2 Answers2

0

First of all you need a state in the parent component of the Home to indicate that the animation is finished. You can pass it to the Home component as a property.

  const [animFinished, setAnimFinished] = React.useState(false);

...

  <Home animFinished={animFinished} setAnimFinished={setAnimFinished} />

Now in the Home component make sure that the animation will not run if the animFinished is true. For example set the from transform the same as the to transform.

Now all you have to do is call setAnimFinished(true) when the animation finished. You can do it in the onRest callback.

  const gameOptionsTransitions = useTransition(true, null, {
    from: {
      opacity: 0,
      transform: animFinished ? "translateY(0)" : "translateY(200px)"
    },
    enter: { opacity: 1, transform: "translateY(0)" },
    leave: { opacity: 0, transform: "translateY(200px)" },
    onRest: () => setAnimFinished(true)
  });

this is an example: https://codesandbox.io/s/react-spring-animation-on-start-only-3ivw8

Peter Ambruzs
  • 7,763
  • 3
  • 30
  • 36
-1

If your app is an SPA all the time so you can make it work with these two solutions:

1. For the fist time that users visit our app(home) and just once:

// Without using any server side session
let showAnimation = localStorage.getItem("show_landing_animation");
if(showAnimation === 0) {
  return <Home animate></Home>
  // After that animation has been finished set the flag as 1 in your 
  // nested spring callback
  localStorage.setItem("show_landing_animation", 1)
}
return <Home></Home>


2. For the every time that users visit our app(home) and just once:

// Store a flag in "localStorage"

let showAnimation = localStorage.getItem("show_landing_animation");
if(showAnimation === 0) {
  // animate
  return <Home animate></Home>
  // After that animation has been finished set the flag as 1 in your 
  // nested spring component callback
  localStorage.setItem("show_landing_animation", 1)
}
return <Home></Home>
// remove the flag on tab close event
window.onbeforeunload = () => {
  localStorage.removeItem("show_landing_animation");
}

Heartbit
  • 1,698
  • 2
  • 14
  • 26