2

I am creating a simple carousel with react and I noticed that my index gets call multiple times and I don't understand why, here is my snippet of code here also here is a full version https://codesandbox.io/s/small-bash-4l7ix?file=/src/index.js

...

const pages = [
  React.forwardRef((props, ref) => (
    <animated.div ref={ref} style={{ ...props.style, background: 'lightpink' }}>
      A
    </animated.div>
  )),
  React.forwardRef((props, ref) => (
    <animated.div ref={ref} style={{ ...props.style, background: 'lightblue' }}>
      B
    </animated.div>
  )),
  React.forwardRef((props, ref) => (
    <animated.div ref={ref} style={{ ...props.style, background: 'lightgreen' }}>
      C
    </animated.div>
  )),
]

export default function App() {
  const [index, set] = useState(0)
  const [containerRef, containerSize] = useDimensions()

  const transitions = useTransition(index, p => p, {
    from: { opacity: 0, transform: 'translate3d(100%,0,0)' },
    enter: { opacity: 1, transform: 'translate3d(0%,0,0)' },
    leave: { opacity: 0, transform: 'translate3d(-50%,0,0)' },
  })
  const divStyle = {
    height: `${containerSize.height}px`,
  }

  console.log(index)
  return (
    <>
      <button className={`btn ${index === 0 ? 'btn--active' : ''}`} onClick={() => set(0)}>
        Slide 1
      </button>
      <button className={`btn ${index === 1 ? 'btn--active' : ''}`} onClick={() => set(1)}>
        Slide 2
      </button>
      <button className={`btn ${index === 2 ? 'btn--active' : ''}`} onClick={() => set(2)}>
        Slide 3
      </button>

      <div style={divStyle} className="simple-trans-main">
        {transitions.map(({ item, props, key }) => {
          const Page = pages[item]
          return <Page ref={containerRef} key={key} style={props} />
        })}
      </div>
      <p> Lorem ipusum</p>
    </>
  )
}

...
Will
  • 1,592
  • 12
  • 22
Kevin
  • 339
  • 1
  • 3
  • 14

2 Answers2

2

This is because of useTransition.

That creates an extra render of sorts, that is why you see index printed multiple times.

I have removed the useTransition and you can check it prints only on index change.

Check below.

Edit gracious-oskar-h6sci

Utsav Patel
  • 2,789
  • 1
  • 16
  • 26
  • So but commenting those out it stops my animation. Seems like a bug within that library i guess. – Kevin May 01 '20 at 16:47
2

In order to transition components in and out the useTransition hook from react-spring keeps track of component instances for you. These extra renders are caused by overlapping mounting and unmounting of nodes.

For example:

  1. Start at 'Slide 1'
  2. Click 'Slide 2'
  3. Library mounts 'Slide 2' // Triggers rerender
  4. Library starts to transition 'Slide 1' out
  5. Library unmounts 'Slide 1' // Triggers rerender

Each transition is pushed into the array and the library animates them in order. So you can trigger multiple overlapping animations simultaneously.

Checkout the React DevTools in the codesandbox and you will see the nodes mounting and unmounting.

React Devtools in codesandbox

Will
  • 1,592
  • 12
  • 22
  • I see and basically this library is causing this sort of rerender issue. Which isn't ideal. – Kevin May 01 '20 at 16:48
  • 1
    It’s generally not a problem if your site isn’t slow. React renders fast. There are ways to optimise it but your should not optimise prematurely. @Kevin – Will May 01 '20 at 21:09
  • Did this answer your question or do you need more info? @Kevin – Will May 04 '20 at 12:10
  • Yeah it is actually a bug within react spring and that it is known thing. Thanks for your input. – Kevin May 04 '20 at 20:27