Introduction
The React Spring library has a modern way of approaching animations by using a physics-based model. You can configure animations using real-life values like mass, friction, and tension, which allow you to create more believable transitions. There is also an option for duration-based approach. The library has great performance and an easy-to-use API. React Spring is cross-platform and has quite a optimal bundle size.
Render props API vs hooks API
The release of React version 16.8 introduced hooks, which enable you to use state, component methods, and other features without writing a class. The React Spring team introduced a new Hooks API in version 7.0. At the moment, there are 5 React Spring hooks: useSpring, useSprings, useTrail, useTransition, and useChain. Hooks allow us to create much cleaner code and avoid so-called render props hell.
Installing
You can check out final code on this GitHub. Clone GitHub repository using this command:
git clone git@github.com:atherosai/next-react-graphql-apollo-hooks.git
Then install npm modules using:
npm i
And finally, use the following command to run the node server:
npm run dev
Animating carousel, changing the text (fade-in, fade-out)
In the following example we will code multiple changing titles, which you can apply to your carousel or whichever way you see fit.
If we want to use items that are added and removed, we need to import the useTransition hook. When we import an animated, we need to put it in front of div to signalise that it is an animated div.
import { useTransition, animated } from 'react-spring';
Using React hooks we can initialise the items array, where each object contains a title string, which will be shown on screen, and an id number, which we will need later on in the transition hooks to identify the specific title.
const [items] = useState([ {title: 'GraphQL changed the way we create software', id: 0}, {title: 'Learn about GraphQL language for free in the browser', id: 1}, {title: 'Learn how to be a lead frontend engineer with GraphQL-driven React and Apollo applications', id: 2}]);
Also, we need to define the index and setIndex state hooks to control the current index of items shown on screen.
const [index, setIndex] = useState(0);
Now we will finally add the transition hook:
const fadingTextPropsTransition = useTransition(items[index], item => item.id, { from: { opacity: 0 }, enter: { opacity: 1 }, leave: { opacity: 0 }, config: { tension: 220, friction: 120 },});
The first argument is the current item of the array; the second one is the item id; and the third is the object where we define the three different stages of animation. These stages are as follows: an animation starts at the from variable, goes to enter and ends at leave.
For this animation, we are going to use the opacity variable, but you can work with any CSS variable for other animations. In this config, we set the tension to 220 and the friction to 120, but try to play around with these values to see what they really do. You can also use some presets for this animation, but they have quite short durations.
These lines in the function component adds a loop using the setInterval function, where the current index is set to another one every 4 seconds. The modulo operator expression assures that when the current index points to the last item, it gets set to the first item. Make sure you clear the interval to avoid memory leaks.
useEffect(() => { const interval = setInterval(() => { setIndex((state) => (state + 1) % items.length); }, 4000); return () => clearInterval(interval);}, []);
You have to create a map function of the transition hooks with the following arguments. The first one is the current item of an array; props are the CSS values; and the key is the specific id you set in the useTransition hook.
Then you can add a special HTML tag, animated.div, which activates the React Spring animation. For this example, I used inline styles so you can see it more clearly. However, the only important style is the absolute position in the div container, so the texts can overlap each other.
{fadingTextPropsTransition.map(({ item, props, key }) => ( <animated.div key={key} style={{ ...props, position: 'absolute' }} > <p className={s.Carousel__Title}> {item.title} </p> </animated.div>))}
Conclusion
If you want to delve deeper into React Spring animations, visit the official React Spring website. You can learn different animation methods using useTrail or useChain hooks, for example, or explore the countless examples posted on the website. Also check out this high-performance boilerplate consisting of React, Apollo, Next.js, GraphQL, and Node.js. You can find the final code on GitHub as well as two other basic loading animations for carousels.