[英]Build reusable Animation component with react-spring without rendering a wrapper element
我想用react-spring构建一个可重复使用的 animation 组件。 这是我到目前为止所拥有的:
const Fade = ({
show,
as = "div",
children
}: {
show: boolean;
as?: keyof JSX.IntrinsicElements;
children: React.ReactNode;
}) => {
const transitions = useTransition(show, null, {
from: { position: "absolute", opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
unique: true
});
const AnimatedComponent = animated[as];
return (
<>
{transitions.map(({ item, key, props }) => {
if (!item) {
return null;
}
return (
<AnimatedComponent key={key} style={props}>
{children}
</AnimatedComponent>
);
})}
</>
);
};
但是,现在存在一个问题,animation 组件引入了“副作用”,在我想要动画的孩子周围添加了一个“div”包装。 这会导致现有组件出现样式问题,需要进行大量更改。
因此,作为一种解决方法,我尝试将animated
用作 function,并将子元素作为非实例化的反应元素传递。 但是随后会出现明显的卡顿,并且 animation 没有完成并有时会在中途停止,例如,检查动画元素,并注意到不透明度倾向于停止在 0.98883393 而不是 1。
const Fade = ({
show,
children
}: {
show: boolean;
children: React.ReactElement;
}) => {
const transitions = useTransition(show, null, {
from: { position: "absolute", opacity: 0 },
enter: { opacity: 1 },
leave: { opacity: 0 },
unique: true
});
// Here's the change. We wrap children in a functional component and clone
// children inside
const AnimatedComponent = animated(({ style }) =>
React.cloneElement(children, { style })
);
return (
<>
{transitions.map(({ item, key, props }) => {
if (!item) {
return null;
}
return (
<AnimatedComponent key={key} style={props}>
{children}
</AnimatedComponent>
);
})}
</>
);
};
我注意到引入额外的“div”包装器似乎是其中一些基于动画的库(如react-spring和framer-motion )的副作用
有没有建议的方法来构建可重复使用的 animation 组件与 react-spring 没有引入额外 DOM 元素的副作用
这是react-spring
的旧版本,从那时起事情发生了变化,所以很难准确地解决为什么你有这种奇怪的行为, opacity
没有达到1.0
。 尽管如此,您在控制台中也会收到有关更新未安装组件的警告,并且key
属性始终undefined
,因此我不确定您是否正确使用了转换。 但是由于 api 文档不再存在,因此很难进行故障排除。
尽管如此,我可以告诉你,没有必要在你的动画内容周围添加一个额外的包装元素。 在第一种情况下,您明确告诉react-spring
添加一个元素( animated.XXX
),它当然会这样做。 在您的第二个(损坏的)示例中,没有包装器,如果您研究如何在旧版本中使用useTransition
,我认为您可以让它工作。
然而,你应该知道react-spring
在最好的时候使用 ref 来更新 React 之外的元素。 这就是为什么animated
提供的所有基本 HTML 元素( animated.div
、 animated.span
等...)都具有您所看到的这种包装行为。 如果你使用animated
来包装你自己的组件,你基本上有两种选择:
animated
到它(使用forwardRef
)。 现在你的组件不会一直重新渲染,而只会重新渲染一次,并且更新将在 React 之外处理。 使用这种方法,您可以确定要将 ref 提供给哪个元素(而不是react-spring
使用包装器为您简化此操作)。 总而言之,这并不能解释opacity
的奇怪之处,但它确实解释了为什么react-spring
更喜欢使用包装器组件,因为这样它可以保证它可以为该元素的所有内容设置动画一种有效的方式。 幸运的是, react-spring
还为您提供了选择所需元素类型的选项。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.