sghall / react-move

React Move | Beautiful, data-driven animations for React
https://react-move-docs.netlify.app
MIT License
6.58k stars 168 forks source link

Caching and events #60

Closed meitalvtn closed 3 years ago

meitalvtn commented 4 years ago

Problem or feature description

  1. When there are animations running in a NodeGroup, the internal animations list never gets cleaned up, which means if there are constantly animations on the screen then the old ones are "leaked" (aren't removed until all animations stop)

  2. On the leave attribute, as more animations are added, the start event is called more and more times (that is, its fired not only by the animations that are actually starting)

  3. Similarly to #1, the end leave callback doesn't get called until all the animations stop.

  4. Calling setState from the start leave callback causes an infinite loop.

All this makes it virtually impossible to remove animations from the DOM so as to not cause a crash.

Steps to reproduce (only needed for problems)

return (
    <svg 
      viewBox="0 0 100 100" 
      xmlns="http://www.w3.org/2000/svg" 
      style={{
        width: '400px',
        height: '700px',
        display: 'block',
        margin: 'auto'
        }} >
      <g transform="translate(50, 100)">
      {animations.map((animation) => <Animate
        key={animation.time}
        show={animation.active}
        start={{
          circle: {
            fill: '#2E86C1',
          },
          g: {
            transform: 'translate(0, 60)',
            opacity: 0,
          },
        }}
        enter={{
          circle: {
            fill: ['#2E86C1'],
          },
          g: {
            transform: 'translate(0,-25)',
            opacity: [1],
          },
          timing: { duration: 200, ease: easeSinOut },
        }}
        leave={{
          circle: {
            fill: ['#A9CCE3'],
          },
          g: {
            opacity: [.1],
            transform: ['translate(0, -200)'],
          },
          events: {
            start: () => {
              console.log('removed', animation.active)
              //setAnimations(animations.splice(animations.indexOf(animation), 1))
            }
          },
          timing: { duration: 4000, ease: easeSinOut },
        }}
        update={{
          g: {
            opacity: 1,
            transform: 'translate(0,-25)',
          },
          timing: { duration: 50, ease: easeSinOut },
        }}
        interpolation={(begValue, endValue, attr) => {
          if (attr === 'transform') {
            return interpolateTransformSvg(begValue, endValue)
          }
          return interpolate(begValue, endValue)
        }}
      >
        {({circle, g}) => (
            <g {...g}>
              <circle style={{x:0, y:0}} r="25" {...circle} />
              <text 
              fill="black" 
              fontSize="15"
              style = {{
                x: "50%", 
                y: "50%", 
                dominantBaseline: "middle",
                textAnchor: "middle",
              }} >
                {animation.chord}
              </text>
            </g>)}
    </Animate>)}
  </g></svg>
  )
}

Versions (only needed for problems)