React Spring 中的 useTransition 导致过多的重新渲染

问题描述 投票:0回答:2

我正在使用

useTransition
中的
react spring
为博客构建动画文字的砖石网格显示。我的工作很大程度上基于 React Spring 的砖石网格的官方 Codesandbox 演示,可以在这里找到:https://codesandbox.io/embed/26mjowzpr

我的作品可以在这里找到:https://codesandbox.io/s/qrzn-issue-2-david-byrne-8s7bo?file=/src/App.js:1267-1293

您会在我的代码和框中注意到,如果您单击底部的一个小头,则会发生转换,但随后页面将重新渲染大约 20 次,我不明白为什么。

我认为这与我调用

useTransition
有关,但我完全不知所措

  const leftTransitions = useTransition(leftGridItems, item => item.word, {
    from: ({ xy, width, height }) => {
      return {
        xy: [xOffset, yOffset],
        width,
        height,
        opacity: 0
      };
    },
    enter: ({ xy, width, height }) => ({ xy, width, height, opacity: 1 }),
    update: ({ xy, width, height }) => ({ xy, width, height }),
    leave: ({ xy, width, height }) => {
      return {
        xy: [xOffset, yOffset],
        opacity: 0
      };
    },
    config: { mass: 5, tension: 500, friction: 100 },
    trail: 25
  });
reactjs animation transition react-spring
2个回答
0
投票

如果有人感兴趣,如果您更新到 v9,这将不再是问题。详细信息请参见此处的变更日志:https://www.react-spring.io/log


0
投票

我通过添加溢出来修复(在这种情况下,我使用的是顺风,所以我只是使用

overflow-x-scroll
max-w-full
。这是示例

        <div
          className={cn(
            "w-full max-w-full disable-scrollbars overflow-x-scroll h-full flex flex-row justify-between phonewide:justify-between items-center",
            "tansition-all duration-300 ease-in-out"
          )}
        >
          <ChevronLeft
            className="phonewide:flex sm:flex lg:w-16 lg:h-16 md:w-10 md:h-10 sm:h-7 sm:w-7 w-7 h-7 text-gray-500"
            onClick={() => {
              setDirection("left");
              if (idx === 0) {
                setIdx(DUM_BATTERY.length - 1);
                return;
              }
              setIdx((state) => (state - 1) % 4);
            }}
          />
          {transitions((style, item, ts) => (
            <animated.div
              key={item.id}
              className={cn(
                "phonewide:space-x-5 sm:space-x-5 space-x-2 lg:space-x-10",
                "flex flex-col items-center justify-center",
                "phonewide:flex-row md:flex-row sm:flex-row",
                "transition-all duration-700 ease-in-out"
              )}
              style={{
                ...style,
                width: "100%",
              }}
            >
              <div>
                <Image
                  src={getBatteryImage(item?.battery?.picture)}
                  width={200}
                  height={220}
                  alt="Battery image"
                  className="rounded-lg h-28 w-28 sm:h-60 sm:w-60 lg:h-72"
                />
              </div>
              <div className="flex flex-col justify-between">
                <div>
                  <p className="text-lg lg:text-xl font-semibold mt-4 sm:mt-0">
                    {item.name}
                  </p>
                  <p className="text-base text-gray-500">
                    Capacity: {batteryMeta.capacity} kWh
                  </p>
                  <p className="text-base text-gray-500">
                    Warranty: {batteryMeta.warranty} Years
                  </p>
                </div>
                {/* desktop view */}
                <div className="flex-col space-y-2 mt-2 w-full hidden sm:flex">
                  <div className="flex items-center justify-between phonewide:justify-center space-x-4 bg-gray-100 rounded-lg px-4 py-2 phonewide:w-min w-full">
                    <button className="text-xl font-semibold text-gray-600">
                      -
                    </button>
                    <span className="text-xl font-medium text-gray-800">1</span>
                    <button className="text-xl font-semibold text-gray-600">
                      +
                    </button>
                  </div>
                  <Button>Select Battery</Button>
                </div>
              </div>
            </animated.div>
          ))}
          <ChevronRight
            className="phonewide:flex sm:flex lg:w-16 lg:h-16 md:w-10 md:h-10 sm:h-7 sm:w-7 w-7 h-7 text-gray-500"
            onClick={() => {
              setDirection("right");
              if (idx === DUM_BATTERY.length - 1) {
                setIdx(0);
                return;
              }
              setIdx((state) => (state + 1) % 4);
            }}
          />
        </div>

配置:

  const [direction, setDirection] = React.useState("right");
  const [idx, setIdx] = React.useState(0);

  const transitions = useTransition(DUM_BATTERY[idx], {
    from: {
      opacity: 0,
      transform:
        direction === "left" ? "translateX(-100%)" : "translateX(100%)",
    },
    enter: { opacity: 1, transform: "translateX(0%)" },
    leave: {
      opacity: 0,
      transform:
        direction === "left" ? "translateX(100%)" : "translateX(-100%)",
    },
    config: {
      ...config.wobbly,
      duration: 700,
    },
    reset: true,
    exitBeforeEnter: true,
  });
© www.soinside.com 2019 - 2024. All rights reserved.