React-spring: Components get duplicated when having a animation on mount and triggering it fast

Created on 27 Jun 2018  路  8Comments  路  Source: pmndrs/react-spring

When having a simple mount/unmount animation on click and when the user presses the mouse button really fast each time the user clicks a new element is created if the animation was not completed. Resulting in many duplicated components and mount triggers. This seems unexpected.

Gif: https://gyazo.com/dea3ca7a09b1ffbb8f0b3f454f906dc1

Code: https://codesandbox.io/s/w0jj62rj45
open up developer tools and click the mouse button very fast on the list. You will see more than 2 components rendered in the dom

I would expect only a maximum of two items to be rendered in this case. Is this a know bug? Or is there a way to fix this? Or can i cancel running animations to avoid this?

question

Most helpful comment

However, i just noticed that when an transition is leaving the component is mounted and unmounted again. Is this also because of this, or is this a separate issue?

This does seem really weird because when i open a modal, and close it I expect it to mount and unmount only once. But when closing it it get's mounted and unmounted again. If i do any heavy data fetching on didMount it would cause some major performance problems.

logging didMount and willUnmount shows this while closing:

mount
unmount
mount
unmount

Code:

<Transition
    from={{ opacity: 0, transform: `scale(0.8)` }}
    enter={{ opacity: 1, transform: `scale(1)` }}
    leave={{ opacity: 0, transform: `scale(0.8)` }}
    config={config.stiff}
>
    {modalIsShown ? styles => (
        <div
            style={{ opacity: styles.opacity }}
            onClick={this.handleOnOverlayClick}
        >
            <div style={styles}>
                Modal content component
            </div>
        </div>
    ) : () => null}
</Transition>

Is there any way to prevent this?

All 8 comments

I'm also seeing this. Mine takes place on hover of any of the thumbnails on this page. http://leveluptutorials.com/tutorials/

Hovering back and forth between two will see the container continually growing each time with additional divs being added.

Any leaving transition gets a unique key and fades out. That is done in order to prevent that key from overriding the element in case it enters again. Fast clicking yields dozens of leaving transitions. Here鈥檚 an example: https://codesandbox.io/embed/yj52v5689 clicking fast shows a stack of old transitions.

Don鈥檛 have a laptop with me right now to check the examples, but are you sure it should be otherwise? If it wouldn鈥檛 isolate dead transitions they would abruptly vanish and reset once the element comes in again with the same key.

@drcmda thanks for the reply. I think i might have been too quick to judge then.

I was confused because In my case i have some data fetching calls in my animated components on mount, and they get called multiple times when clicking fast, resulting in many network requests. I think i can fix this by only fetching the data once the animation is finished. Are there any "onEntered" properties, to listen for animation to be completed? I don't see something like an onRest prop on Transition components in the API docs

However, i just noticed that when an transition is leaving the component is mounted and unmounted again. Is this also because of this, or is this a separate issue?

This does seem really weird because when i open a modal, and close it I expect it to mount and unmount only once. But when closing it it get's mounted and unmounted again. If i do any heavy data fetching on didMount it would cause some major performance problems.

logging didMount and willUnmount shows this while closing:

mount
unmount
mount
unmount

Code:

<Transition
    from={{ opacity: 0, transform: `scale(0.8)` }}
    enter={{ opacity: 1, transform: `scale(1)` }}
    leave={{ opacity: 0, transform: `scale(0.8)` }}
    config={config.stiff}
>
    {modalIsShown ? styles => (
        <div
            style={{ opacity: styles.opacity }}
            onClick={this.handleOnOverlayClick}
        >
            <div style={styles}>
                Modal content component
            </div>
        </div>
    ) : () => null}
</Transition>

Is there any way to prevent this?

I have the same issue, components duplicate when clicked on them

https://codesandbox.io/s/32wy3vyxz5

@ilyanoskov from what i see the behavior is correct, the only thing that seems wrong is the component definition, it should be:

const ComponentA = style => ...
const ComponentB = style => ...

If you want them to fade out on top of one another you should also make these divs absolute. Otherwise they'll be stacked naturally.

The whole point of transition is that it retains the last state of an element that's actually gone from the react tree. It retains it until the spring that drives its leave-state has completed, then it goes away completely.

@ilyanoskov would you amend your sandbox to showcase the mount/unmount stuff? i'll take a closer look.

will re-open when there's more data to inspect

Was this page helpful?
0 / 5 - 0 ratings

Related issues

n1ru4l picture n1ru4l  路  3Comments

fortezhuo picture fortezhuo  路  3Comments

Daniel15 picture Daniel15  路  3Comments

mkhoussid picture mkhoussid  路  3Comments

anton-g picture anton-g  路  3Comments