react-native-web
react-native-web copied to clipboard
Keyframe Animation only works with StyleSheet.create and within on Animated.View
Is there an existing issue for this?
- [X] I have searched the existing issues
Describe the issue
(this might be too issues, but I guess that they are probably based on the same underlying problem) Hi 👋
I recently upgraded from 0.11 to 0.18 and noticed that our loading indicators are broken (no longer animated). I noticed that the CSS property animationKeyframes is only respected if
- The element is a View (Animated.View does not work)
- The animation is passed through
StyleSheet.create, inline styling does not work
The generated CSS contains all CSS animation properties (like animation-timing-function) except animation-name.
Expected behavior
Animation keyframes should be generated and work when using inline styles and/or Animated.View.
All Views should rotate in the provided test case.
Steps to reproduce
Use React Native Web 0.18.0. (See attached codesandbox)
const animation = {
animationKeyframes: [
{
"0%": { transform: [{ rotate: "0deg" }] },
"100%": { transform: [{ rotate: "360deg" }] }
}
],
animationDuration: "750ms",
animationIterationCount: "infinite",
animationTimingFunction: "linear",
animationPlayState: "running"
};
const Styles = StyleSheet.create({
animation
});
then render views
<Animated.View
style={[
{
width: 100,
height: 100,
backgroundColor: "red"
//...animation
}
]}
>
<Text>Animated.View inline!</Text>
</Animated.View>
<Animated.View
style={[
{
width: 100,
height: 100,
backgroundColor: "red"
},
Styles.animation
]}
>
<Text>Animated.View StyleSheet!</Text>
</Animated.View>
<View
style={[
{
width: 100,
height: 100,
backgroundColor: "green",
...animation
}
]}
>
<Text>View inline!</Text>
</View>
<View
style={[
{
width: 100,
height: 100,
backgroundColor: "green"
},
Styles.animation
]}
>
<Text>View StyleSheet!</Text>
</View>
Observe that only the last View (with Text "View StyleSheet!") will start to rotate.
Test case
https://codesandbox.io/s/react-native-keyframe-animation-bug-ts4ib9
Additional comments
Thanks for being such a pillar of the React (Native) community!
FWIW inline style animations haven't been supported for a long time. I'll look into why the Animated one doesn't work
Oh it's because Animated calls StyleSheet.flatten which produces a new style object no longer recognized by the compiler (which doesn't produce class names at render time anymore, for React 18 reasons). You can consider Animated as only supporting inline styles at the moment. Is there a reason why you're trying to use CSS Animations with the Animated API, rather than using only one or the other?
I might have a fix for this. I'll hopefully get a patch up soon for you to try in your environment
The reason for it was a single component for web and native, but using css animations on web and native Animated otherwise. I could have done it differently but there was no reason for completely separate components.
Using Animated for the loading indicator was especially fragile as the indicator hides a lot of JS main thread work.
There is also a loading placeholder component that can get the opacity animated value from the parent, while also having an additional css animation that runs every time. I solved that by wrapping it into another Animated.View.
Is there a specific reason why inline animations are not supported? (I guess performance?) I find it a bit weird that animation-name is just missing. Could there at least be a warning or is it hard to detect?
I could have done it differently but there was no reason for completely separate components.
Why not use View for web and Animated.View for native? That seems like a relatively simple conditional that avoids the overhead of all the Animated implementation on web if you're not using it at all
Is there a specific reason why inline animations are not supported? (I guess performance?)
Because inline styles are not converted to CSS rules, but animations require CSS rules and keyframes.
Why not use View for web and Animated.View for native?
🤷♂️ Well, now I am since 0.18 😜
Thanks for the insight, makes sense!
Awesome, you are the best, @necolas! 👍