Reputation: 12819
I have React code like this:
handleTransitionEnd() {
console.log('ended');
}
<div onTransitionEnd={(ev) => this.handleTransitionEnd(ev)}....
The peculiar thing is that my logs are filling up with ended
. Even if I don't have any transition css logic tied to the element at all. It seems to be firing on every state change or re render. Is this normal? I would expect it to only fire when a css transition ends.
Is there some other way this callback should be achieved?
Thanks
UPDATE:
here is a sandbox showing some strangeness: https://codesandbox.io/s/vy5wwyq5v3
Clicking the first button causes the callback to be called 3 times, then if you click the second button it gets called another 2 times even tho a transition doesn't happen. My app is even more extreme than this with it getting called a lot more often.
Upvotes: 3
Views: 16780
Reputation: 260
To add on to what dabs said in his answer, the transitionend
event bubbles. This means if any children of your element have transitions on them, they will trigger the transitionend event on themselves, then bubble up to their parent, triggering on each of them, including the current element that you have the listener on.
A simple way to check that you're only running your logic for the element your listener is on is to compare e.target
and e.currentTarget
like so:
onTransitionEnd={e => {
if ( e.target === e.currentTarget ) {
// your logic here
}}
e.target
is the element that starts the event, which can be one of the children, for example, not just the element with the listener on it.
e.currentTarget
however always points to the element that has the listener on it, regardless of if it initiated the event or not.
By comparing the two, you can check that you're only running logic when it's the element with the listener on it that initiated it.
Upvotes: 1
Reputation: 51
The css transition being used transition: "all 3s"
is causing transitions on multiple properties, not just margin-left.
In the example provided, outline-color
and outline-width
were transitioned as well. They were then transitioned again when clicking anywhere else (not just on the second button).
You can see this by checking the event:
onTransitionEnd={e => {
e.persist(); // see: https://reactjs.org/docs/events.html#event-pooling
console.log(e.propertyName);
}}
The css transition could be more specific: transition: "margin-left 3s"
to avoid this.
Alternatively, test e.propertyName
for the desired case.
Upvotes: 5