Creating a placeholder loading Component in React Native using Animated
I’m creating a React Native component that shows as a placeholder for live data (in other words: loading boxes) and changing it’s color to indicate that stuff is loading..
Here’s how you go about doing that:
- Create a new
Animated
value, and give it the initial value.
// set a value to be animated
const currentColor = new Animated.Value(0)
- To change color you can use
.interpolate()
on the animated value you just created. Interpolate will take an array of input valuesinputRange
, and another one of output valuesoutputRange
, and then map the values to each other. You can either do this interpolation inside yourAnimate
function, or you can define it separately, which i did, like so:
// interpolate color value
const changeColor = currentColor.interpolate({
inputRange: [0, 1, 2],
outputRange: ['gainsboro', 'whitesmoke', 'gainsboro']
})
What the code above would mean is that at my initial value of 0
, the color would be gainsboro
and when i move to 1
it’ll change to whitesmoke
. Then i’m changing it back to gainsboro
at 2
(because i want to loop the color change). If you set the toValue
as 1
in the above code, it’ll only transition till whitesmoke
and ignore what comes afterwards.
- Now, that i have the values defined, i’m going to setup my animation:
// define the looping animation
const animateColor = ()=> {
Animated.loop(
Animated.sequence([
Animated.timing(currentColor, {
toValue: 2, // the value in interpolated output range that you want to go to
duration: 2000 // ms
}),
])
).start()
}
In my animation, i’ll loop
a sequence
of changes. Inside the sequence, i’m animating between different values (mapped to my colors above). Using the .timing()
function, i’m changing the value i want to animate (defined as currentColor
) over a period of 2000ms (i.e. 2sec) and going from the initial value of 0
to the interpolated value of 2
(using toValue
).
The above two steps can also be combined like so:
- I’m starting the animation and saving the entire process as a function called
animateColor
. I’ll then pass that function to theuseEffect()
hook (i.e. the equivalent ofcomponentDidMount()
)
export default function App() {
useEffect(() => {
// start the animation to change background color
animateColor()
})
return (
// component goes here..
);
}
In your component, when you’re setting styles, you’ll use the Animated.Value
you defined in order to change color, in our case backgroundColor: changeColor
Here’s the full code:
import React, { useEffect } from 'react'
import { Animated, StyleSheet, View } from 'react-native'
// set a value to be animated
const currentColor = new Animated.Value(0)
// interpolate color value
const changeColor = currentColor.interpolate({
inputRange: [0, 1, 2], // the values that the animation will transition from
outputRange: ['gainsboro', 'whitesmoke', 'gainsboro'] // values that are animating
})
// define the looping animation
const animateColor = ()=> {
Animated.loop(
Animated.sequence([
Animated.timing(currentColor, {
toValue: 2, // the value in interpolated output range that you want to go to
duration: 2000 // ms
}),
])
).start()
}
export default function App() {
useEffect(() => {
// start the animation to change background color
animateColor()
})
return (
<View style={styles.container}>
<Animated.View style={{ height: 150, width: 150, backgroundColor: changeColor, borderRadius: 8, margin: 8}}></Animated.View>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Notes
- The above code is now in a good place to be used as a starting point. If you want to use
rgba
values, you may have to look intohex-to-rgba
- The entire thing could just be a CSS animation as well, look into that. I mean, we’re only changing the background color? Answer: In vanilla React Native you can not use CSS animations. The
Stylesheet
properties in React Native are pretty limited. You can find a list of all supported properties here - But maybe we can do CSS animations using
styled-components
?
Animating SVGs
Can i use SVGs as placeholder? Sure. you’d have to use another library (e.g. react-native-svg
)to add SVG support to React Native, and then you’d have to create a custom animated components using createAnimatedComponent to be able to animate an <Svg>
component
See example here
import { Path } from "react-native-svg";
const AnimatedPath = Animated.createAnimatedComponent(Path);
See [Animating SVG in React Native]()