首页 > 解决方案 > 如何使用 react-spring 制作一个 react 自定义组件动画

问题描述

我有一个名为 react 的自定义组件HomeContent,它接受一些道具。

根据我制作的 react-spring 文档制作动画

const animatedHomeContent = animated(HomeContent);

然后为了渲染,我这样做了:

 <animatedHomeContent
    id={1}
    avatar="O"
    image="..."
    image_title="Onion"
    title=" Medium Sized Onions"
    subtitle="November 08, 2020"
    desc="Onions from farms of Nasik"
    price="74"
    quantity="1kg"
/>

但我看到道具没有通过。请告诉我该怎么做。

标签: javascriptreactjsreact-spring

解决方案


这取决于你想如何与你的组件交互,你想使用 api 还是仅仅提供更新的 props?

// update by regenerating springProps from some other state
const springProps = useSpring(props) 

// update springProps with api
const [springProps, api] = useSpring(() => props) 

通过再生弹簧进行更新

对于第一个示例,使用其中一个动画原生元素animated.XXXspringProps重新渲染。或者......这只是部分正确,SpringValue返回对象中的 individual 将与两种方法相同,因此如果您将它们作为单独的道具传递,理论上不需要重新渲染,但如果您将它们作为一个整体对象传递(例如whenspringProps是一个style对象)它将是上次渲染的更改对象并导致animated包装器的重新渲染。

当您使用在包装器内不使用 ref 而不是本机元素之一的自定义元素时,组件将为每个动画帧重新渲染一次。从性能的角度来看,这是次优的,但是通过这种策略,您可以为组件使用所需的任何 api(prop 名称),就像您所做的那样。

这是一个使用此解决方案的沙箱:沙箱

您可以观察到动画有效,而且组件重新渲染了很多。

通过 api 更新

如果你想让它更高效,并使用 api 来更新你的自定义组件,你需要遵守一些规则。当您使用 api 时,react-spring通过相应 DOM 元素上的 ref 更新元素,因此,react-spring必须了解如何更新元素而不需要 React 重新渲染它。这意味着:

  • 您的自定义元素必须能够持有 ref
  • 您的自定义元素必须将 ref 附加到您希望在其上发生所有动画的 DOM 元素。因为forwardRef不允许您添加多个 refs,所以如果您想包装自定义组件内的多个 DOM 元素,则无法对其进行更改animated(还有其他策略可以解决此问题,例如不包装您的组件animated,而是使用本机animated.XXX组件内的元素并将SpringValues 作为道具传递)。
  • 您的自定义组件的属性名称必须与您要在 ref 附加到的 DOM 元素上更新的属性相对应。否则react-spring将无法理解如何更新此元素。

由于您的元素有很多自定义属性,react-spring因此无法通过 api 更新您的组件。它将尝试通过简单地在 ref 附加到的元素上设置更新的属性来做到这一点,但是由于您需要 React 将自定义属性映射到 DOM 元素上的实际属性,这将失败(我没有知道有您提供的一组属性)。

作为如何完成此操作的示例,以下是一个显示此策略大纲的沙箱:沙箱

在这里你可以看到组件只渲染一次并且仍然可以更新。您还可以看到,包装在自定义组件上的属性animated对应于div元素上的 props,从而react-spring能够完全按照我们的意愿行事(the 的子项AnimatedHomeContent是 React 中名为的特殊 prop,props.childrenreact-spring知道如何处理)。

<AnimatedHomeContent style={{ backgroundColor: spring.backgroundColor }}>
    {spring.content}
</AnimatedHomeContent>

在沙箱中也是一个使用其他属性名称的坏例子。

<AnimatedHomeContentBad
    backgroundColor={spring.backgroundColor}
    content={spring.content}
/>

为了从这个版本中获得正确的行为,React 必须处理组件以将输入道具映射到本机 DOM 元素道具。通过 api 更新此版本时,react-spring不会重新渲染组件(因为它可以使用 ref),而是在 ref 附加到的元素上设置更新的属性(检查控制台中的元素以亲自查看这些道具更新后设置)。由于属性不是真正的属性,因此组件上没有任何更新或动画。


推荐阅读