How to stop a parent's onAnimationEnd from running when a Child run an animation

Viewed 209

I have this simple code where I have A Parent div and a Child Div, both have their own Animations and a button that start the animation and both have an onAnimationEnd Event that display on the console a message.

Whenever I click on the parent button the animation start and when it's over I have the right message on the console.

  Parent Ended Animation

till now No Problems.

when I click on the Child button the animation start and when it's over I get the Child's message and the parent's message.

Child Ended Animation App.

Parent Ended Animation App

.

and that is my problem.

So How Can I stop the parent event from running when the child animation is over?

const ParentAnimation = keyframes`
  from {
    background-color: red;
  }to {
    background-color: blue;
  }
`
const Parent = styled.div`
  background-color: red;
  height: 300px;
  width: 300px;
  animation: ${(props) =>
    props.animate &&
    css`
      ${ParentAnimation} .5s
    `};
`

const ChildAnimation = keyframes`
  from {
    background-color: green;
  }to {
    background-color: yellow;
  }
`
const Child = styled.div`
  background-color: green;
  height: 100px;
  width: 100px;
  position: relative;
  top: 100%;
  animation: ${(props) =>
    props.animate &&
    css`
      ${ChildAnimation} .5s
    `};
`
function App() {
  const [animeteParent, setAnimeteParent] = useState(false)
  const [animeteChild, setAnimeteChild] = useState(false)
  return (
    <Parent
      animate={animeteParent}
      onAnimationEnd={() => console.log('Parent Ended Animation')}
    >

      <Child
        animate={animeteChild}
        onAnimationEnd={() => console.log('Child Ended Animation')}
      >
      </Child>

      <button
        onClick={() => {
          setAnimeteParent(true)
        }}
      >
        Animate Parent
      </button>

      <button
        onClick={() => {
          setAnimeteChild(true)
        }}
      >
        Animate Child
      </button>

    </Parent>
  )
}
1 Answers

call event.stopPropagation(); in your function to stop the event from bubbling up.

Event bubbling

What you're seeing is called 'Event bubbling'. It's not unique to react, and actually a pattern used in most html onXYZ() handlers. In this case, it doesn't really make sense to let 'animation end' bubble all the way to the top.
I guess confirming to a standard way to handle events outweighed making exceptions per event type.

For click events, it can make sense to bubble things up, imagine 5 nested divs, one could make the case that clicking a child is the same as clicking the parent. so we should fire the 'onclick' of the parent as well.

this is called bubbling; as long a now one stops the it, the event will bubble up through all the parents. so that parents can handle the event. (it bubbles through event handlers that share their name, onclick to onclick, onAnimationEnd to onAnimationEnd, etc)

Stopping the bubble

It's easy to stop an event from bubbling. by calling event.stopPropagation(); It's up to developers to determine when they want to allow something to bubble up the the parents or not;

adding the stopPropagation on the child should stop the parent from triggering their event when the child finishes.

 onAnimationEnd={(event) => {
          console.log("Child Ended Animation");
          event.stopPropagation();
        }}

Example

there's a code pen example showing this

Related