useTransition 立即挂载新对象

useTransition mounts new object instantly

我正在尝试弄清楚如何利用 useTransition 进行页面转换(简单的不透明度更改,第一页淡出,新页面淡入)。

到目前为止我有这个小演示 https://codesandbox.io/s/sleepy-knuth-xe8e0?file=/src/App.js 它有点管用,但很奇怪。当转换开始时,新页面立即安装,而旧页面开始动画。这会导致各种布局问题,这不是我想要的行为。是否可以让第一个元素淡出,然后才挂载和淡入第二个元素?

与演示关联的代码

import React, { useState } from "react";
import "./styles.css";
import { useTransition, a } from "react-spring";

export default function App() {
  const [initial, setInitial] = useState(true);
  const transition = useTransition(initial, {
    from: { opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  });

  return (
    <div>
      {transition((style, initial) => {
        return initial ? (
          <a.h1 style={style}>Hello Initial</a.h1>
        ) : (
          <a.h1 style={style}>Hello Secondary</a.h1>
        );
      })}
      <button onClick={() => setInitial(prev => !prev)}>Change Page</button>
    </div>
  );
}

您需要添加 position: absolute 然后您需要使用 css 设置正确的位置。

import React, { useState } from "react";
import "./styles.css";
import { useTransition, a } from "react-spring";

export default function App() {
  const [initial, setInitial] = useState(true);
  const transition = useTransition(initial, {
    from: { position: 'absolute', opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 }
  });

  return (
    <div>
      {transition((style, initial) => {
        return initial ? (
          <a.h1 style={style}>Hello Initial</a.h1>
        ) : (
          <a.h1 style={style}>Hello Secondary</a.h1>
        );
      })}
      <button onClick={() => setInitial(prev => !prev)}>Change Page</button>
    </div>
  );
}

您可以通过等待离开动画完成来延迟过渡的开始。

const sleep = t => new Promise(res => setTimeout(res, t));

...

const transition = useTransition(initial, {
  from: { position: "absolute", opacity: 0 },
  enter: i => async next => {
    await sleep(1000);
    await next({ opacity: 1 });
  },
  leave: { opacity: 0 }
});

这也是第一次延迟动画 运行。你可以有一个 ref 来跟踪组件是否已经渲染过或者它是否是第一次渲染,然后如果它是第一次渲染你可以跳过 sleep 调用。

您只需提供trail配置

const transition = useTransition(initial, {
    from: { position: "absolute", opacity: 0 },
    enter: { opacity: 1 },
    leave: { opacity: 0 },
    trail: 300
  });