# Creating a custom hook for dual animation state

So recently I created a custom hook called `useAnimationState` to return me either of the two states - `AnimationSfdsfdsftate.ZERO` or `AnimationState.ONE` based on the transition times for both. Let's go through the thought process behind it.

So consider a scenario where you have an animation like **fade in** and **fade out**.

Now you would like to perform **fade in** after `x` time and **fade out** after `y` time and they should repeat in these cycles.

This was our specific use case and the earlier code worked well for accommodating it. But I saw an opportunity to make this behavior reusable.

So the fancy code looks like this :-

```plaintext
function useAnimationState (defaultState: string, 
 zeroToOneTransitionTime: number, 
 oneToZeroTransitionTime: number) {

  const [animationState, setAnimationState] = useState(defaultState);

  useEffect(() => {

    let stateOneTimer: ReturnType<typeof setTimeout>;
    let stateZeroTimer: ReturnType<typeof setTimeout>;

    if (animationState === AnimationState.ONE) {
      stateZeroTimer = setTimeout(() => {
        setAnimationState(AnimationState.ZERO);
      }, oneToZeroTransitionTime);
    }

    else {
      stateOneTimer = setTimeout(() => {
        setAnimationState(AnimationState.ONE);
      }, zeroToOneTransitionTime);
    }

    return () => {
      if (stateOneTimer) clearTimeout(stateOneTimer);
      if (stateZeroTimer) clearTimeout(stateZeroTimer);
    };

  }, [animationState, oneToZeroTransitionTime, zeroToOneTransitionTime]);
  return animationState;
}
```

One may ask, that's all cool but the heck is happening here ?

Before that, let's get one thing clear i.e. what is `AnimationState` ?

Well that's just my way of making things more verbose.

Let's create an object called `AnimationState` like so :-

```js
const AnimationState = {
   ONE:"1",
   ZERO:"0"
}
```

Note - Going forward I will mostly be talking in terms of 0 and 1 since that is not so verbose.

Now back to what's happening inside the hook :-

1. `useAnimationState` takes 3 parameters - `defaultState` (either of `AnimationState.ZERO` or `AnimationState.ONE`) , `zeroToOneTransitionTime` and `oneToZeroTransitionTime` (time taken to go from 0 to 1 and vice-versa).
    
2. We have a `animationState` with initial value of `defaultState` with it's respective setter. This is the state which our custom hook will return.
    
3. We have an useEffect inside which we are maintaining two timeouts. Simply put,
    

* if the `animationState` is 1, we will run the callback inside timeout which sets the `animationState` to 0 after `oneToZeroTransitionTime`
    
* else we will run the callback inside timeout which sets the `animationState` to 1 after `zeroToOneTransitionTime`
    

1. Then the obvious cleanup function being returned from useEffect to prevent memory leak by clearing out the set timers.
    

**Notice that** `animationState` is a dependency in `useEffect's` dependency array and is the reason why we are able to execute everything beautifully.

So once you get the `animationState`, how do you plan to use it ?

Well here is our partial use case :-

```js
const HelloFadeClass = {
  [AnimationState.ONE]: 'HomeHero__hello-world--fade-in',
  [AnimationState.ZERO]: 'HomeHero__hello-world--fade-out',
};
```

And inside any component that has makes use of this fade animation, you can have following for an element, say - `span` :-

```jsx

const animationState = useAnimationState(AnimationState.ZERO,1000,4000);

<span className={HelloFadeClass[animationState])}>{helloText}</span>
```

Now you may think, why bother creating all this when you can have everything achieved using **CSS animations** hacks ?

To a certain extent yes but stuff like transition time should be programmable and an `animationState` as a result of that transition can cover multiple use cases.

Our full use case was to shuffle a word at fixed intervals and display on the Home page with **fade in, fade out** animations. Shuffling seems easy but when to do that ?

That right there is where `animationState` comes in !!

We only shuffle when the `animationState` transitions from 1 to 0 so that when it is 1 again, the shuffled text is visible via a **fade in**.

Related code:-

```plaintext
  const animationState = useAnimationState(AnimationState.ONE, 1000, 4000);
  const shouldShuffle = useRef(false);
  const helloText = useShuffle(defaultHelloWorld, HelloWorld, HelloWorldKeys, shouldShuffle.current);

  useEffect(() => {
    shouldShuffle.current = animationState === AnimationState.ZERO;
  }, [animationState]);
```

Do give this a &lt;3 if you found this useful !

Checkout the full usage of hook here :- https://github.com/thenewboston-developers/Website/blob/development/src/containers/Home/HomeHero/index.tsx
