【问题标题】:Ensure entrance css transition with React component on render确保在渲染时使用 React 组件进行入口 css 转换
【发布时间】:2020-12-06 02:50:30
【问题描述】:

我正在尝试在 React 中构建一个准系统 css 转换包装器,其中一个布尔属性控制一个 HTML 类,用于切换设置为转换的 css 属性。对于有问题的用例,我们还希望在入口转换之前和退出转换之后卸载组件 (return null)。

为此,我使用了两个布尔状态变量:一个控制安装,另一个控制 HTML 类。当props.infalse 变为true 时,我将mounted 设置为true。现在的诀窍是:如果类在第一次渲染时立即设置为"in",则不会发生转换。我们需要先用 "out" 类渲染组件,然后将类更改为 "in"

setTimeout 可以工作,但非常随意,并不严格与 React 生命周期相关联。我发现即使是 10 毫秒的超时有时也无法产生效果。这是一个废话。

我曾认为使用useEffectmounted 作为依赖项会起作用,因为组件将被渲染并且效果会发生在:

  useEffect(if (mounted) { () => setClass("in"); }, [mounted]);

(请参阅下面上下文中的完整代码)

但这无法产生过渡。我相信这是因为 React 会批处理操作并选择何时渲染到真实的 DOM,并且大多数时候直到效果也发生之后才会这样做。

我如何保证我的类值仅在 mounted 设置为 true 之后呈现组件之后才发生更改?

简化的 React 组件:

function Transition(props) {
  const [inStyle, setInStyle] = useState(props.in);
  const [mounted, setMounted] = useState(props.in);

  function transitionAfterMount() {
    // // This can work if React happens to render after mounted get set but before
    // // the effect; but this is inconsistent. How to wait until after render?
    setInStyle(true);

    // // this works, but is arbitrary, pits UI delay against robustness, and is not
    // // tied to the React lifecycle
    // setTimeout(() => setInStyle(true), 35);
  }

  function unmountAfterTransition() {
    setTimeout(() => setMounted(false), props.duration);
  }

  // mount on props.in, or start exit transition on !props.in
  useEffect(() => {
    props.in ? setMounted(true) : setInStyle(false);
  }, [props.in]);

  // initiate transition after mount
  useEffect(() => {
    if (mounted) { transitionAfterMount(); }
  }, [mounted]);

  // unmount after transition
  useEffect(() => {
    if (!props.in) { unmountAfterTransition(); }
  }, [props.in]);

  if (!mounted) { return false; }

  return (
    <div className={"transition " + inStyle ? "in" : "out"}>
      {props.children}
    </div>
  )
}

示例样式:

.in: {
  opacity: 1;
}
.out: {
  opacity: 0;
}
.transition {
  transition-property: opacity;
  transition-duration: 1s;
}

及用法

function Main() {
  const [show, setShow] = useState(false);
  return (
    <>
      <div onClick={() => setShow(!show)}>Toggle</div>
      <Transition in={show} duration={1000}>
        Hello, world.
      </Transition>
      <div>This helps us see when the above component is unmounted</div>
    </>
  );
}

【问题讨论】:

    标签: reactjs react-hooks css-transitions


    【解决方案1】:

    在 React 之外找到了解决方案。使用 window.requestAnimationFrame 允许在下一次 DOM 绘制之后执行操作。

      function transitionAfterMount() {
        // hack: setTimeout(() => setInStyle(true), 35);
        // not hack:
        window.requestAnimationFrame(() => setInStyle(true));
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 2019-12-31
      • 2019-09-09
      • 1970-01-01
      • 2021-02-04
      • 2020-01-15
      • 1970-01-01
      相关资源
      最近更新 更多