React useState 重新渲染太多次

React useState re rendering too many times

我正在用 React 创建一个简单的旋转木马,我注意到我的索引被多次调用,我不明白为什么,这里是我的代码片段,这里也是完整版本 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>
    </>
  )
}

...

这是因为useTransition.

这会产生额外的渲染效果,这就是为什么您会看到多次打印索引。

我已经删除了 useTransition,您可以检查它是否仅在 index 更改时打印。

检查下方。

为了转换组件进出 react-spring 的 useTransition 挂钩会为您跟踪组件实例。这些额外的渲染是由节点的重叠安装和卸载引起的。

例如:

  1. 开始于 'Slide 1'
  2. 点击'Slide 2'
  3. 库挂载 'Slide 2' // 触发重新渲染
  4. 库开始转'Slide 1'出
  5. 库卸载'Slide 1' // 触发重新渲染

每个转换都被推入数组,库按顺序为它们设置动画。所以你可以同时触发多个重叠的动画。

检查codesandbox中的React DevTools,你会看到节点挂载和卸载。