DEV Community

Cover image for Enhancing Your React Native App with Reanimated 3 Using Expo
3a5abi 🥷
3a5abi 🥷

Posted on • Originally published at devtoys.io

Enhancing Your React Native App with Reanimated 3 Using Expo

Animations can significantly enhance the user experience of any mobile application. They make interactions feel more intuitive, provide feedback, and create a polished, professional look. However, achieving smooth, high-performance animations in React Native can be challenging due to the JavaScript thread’s limitations. This is where Reanimated 3 comes in. This powerful library allows developers to create complex, performant animations with ease. In this blog post, we’ll explore how to use Reanimated 3 to build high-performance animations in your React Native app using Expo.


Why Reanimated 3?

Reanimated 3 stands out from other animation libraries because it runs animations on the UI thread, not the JavaScript thread. This means animations remain smooth and responsive, even under heavy load or when the JavaScript thread is busy. Reanimated 3 also introduces a new declarative API, making it easier to create and manage animations.


Setting Up Reanimated 3

Setting up Reanimated 3 with Expo is straightforward. Follow the steps below to get started.


Step 1: Create a New Expo Project

First, we need to create a new Expo project using the Reanimated template:

yarn create expo-app my-app -e with-reanimated
cd my-app
yarn start --reset-cache
Enter fullscreen mode Exit fullscreen mode

Creating Basic Animations

Let’s start with a simple animation example: changing the width of a box when a button is pressed.


Sample Animated App Code

The following code is for the App.js file created during the setup:

import Animated, {
  useSharedValue,
  withTiming,
  useAnimatedStyle,
  Easing,
} from "react-native-reanimated";
import { View, Button } from "react-native";
import React from "react";

export default function AnimatedStyleUpdateExample(props) {
  const randomWidth = useSharedValue(10);

  const config = {
    duration: 500,
    easing: Easing.bezier(0.5, 0.01, 0, 1),
  };

  const style = useAnimatedStyle(() => {
    return {
      width: withTiming(randomWidth.value, config),
    };
  });

  return (
    <View
      style={{
        flex: 1,
        alignItems: "center",
        justifyContent: "center",
        flexDirection: "column",
      }}
    >
      <Animated.View
        style={[
          { width: 100, height: 80, backgroundColor: "black", margin: 30 },
          style,
        ]}
      />
      <Button
        title="toggle"
        onPress={() => {
          randomWidth.value = Math.random() * 350;
        }}
      />
    </View>
  );
}
Enter fullscreen mode Exit fullscreen mode

🤔 Looking for a resource to power up your React Native skills? Search no more! Check out this AMAZING hands-on guide. 🔥

React and React Native: A complete hands-on guide to modern web and mobile development with React.js


🤓 Practical Tutorial: Building an Animated To-Do List 🛸

Now, let’s build a practical example – an animated to-do list app using Reanimated 3. This app will allow users to add, remove, and reorder tasks with smooth animations.


✨ TL;DR – Checkout the GitHub Repo!✨

🔗 ===> judescripts/rn-reanimated: DevToys.io blog tutorial on working with React Native Reanimated 3 (github.com)


Step 1: Set Up the Project

Create a new Expo project if you haven’t already:

yarn create expo-app my-todo-app -e with-reanimated
cd my-todo-app
Enter fullscreen mode Exit fullscreen mode

Step 2: Install react-native-gesture-handler

Ensure react-native-gesture-handler is installed:

yarn add react-native-gesture-handler
Enter fullscreen mode Exit fullscreen mode

Step 3: Implement the To-Do List

Create the ToDoList.js component:

import React, { useState } from 'react';
import { View, TextInput, Button, StyleSheet, FlatList } from 'react-native';
import TaskItem from './TaskItem';

const ToDoList = () => {
  const [tasks, setTasks] = useState([]);
  const [task, setTask] = useState('');

  const addTask = () => {
    if (task.trim()) {
      setTasks([...tasks, { id: Date.now().toString(), title: task }]);
      setTask('');
    }
  };

  const removeTask = (id) => {
    setTasks((prevTasks) => prevTasks.filter((item) => item.id !== id));
  };

  const renderItem = ({ item }) => (
    <TaskItem item={item} removeTask={removeTask} />
  );

  return (
    <View style={styles.container}>
      <TextInput
        style={styles.input}
        value={task}
        onChangeText={setTask}
        placeholder="Add a task"
      />
      <Button title="Add Task" onPress={addTask} />
      <FlatList
        data={tasks}
        renderItem={renderItem}
        keyExtractor={(item) => item.id}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    padding: 20,
  },
  input: {
    height: 40,
    borderColor: 'gray',
    borderWidth: 1,
    marginBottom: 10,
    paddingHorizontal: 10,
  },
});

export default ToDoList;
Enter fullscreen mode Exit fullscreen mode

Create the TaskItem.js component using the new Gesture Handler API:

import React from 'react';
import { Text, StyleSheet } from 'react-native';
import Animated, { useSharedValue, useAnimatedStyle, withSpring, withTiming, runOnJS } from 'react-native-reanimated';
import { Gesture, GestureDetector } from 'react-native-gesture-handler';

const TaskItem = ({ item, removeTask }) => {
  const translateX = useSharedValue(0);
  const taskHeight = useSharedValue(70);

  const animatedStyle = useAnimatedStyle(() => {
    return {
      transform: [{ translateX: translateX.value }],
      height: taskHeight.value,
      opacity: taskHeight.value / 70,
    };
  });

  const panGesture = Gesture.Pan()
    .onBegin(() => {
      // Initialize context here if needed
    })
    .onUpdate((event) => {
      translateX.value = event.translationX;
    })
    .onEnd(() => {
      if (translateX.value < -150) {
        translateX.value = withTiming(-200);
        taskHeight.value = withTiming(0, {}, () => {
          runOnJS(removeTask)(item.id);
        });
      } else {
        translateX.value = withSpring(0);
      }
    });

  return (
    <GestureDetector gesture={panGesture}>
      <Animated.View style={[styles.task, animatedStyle]}>
        <Text>{item.title}</Text>
      </Animated.View>
    </GestureDetector>
  );
};

const styles = StyleSheet.create({
  task: {
    height: 70,
    backgroundColor: 'lightgrey',
    justifyContent: 'center',
    paddingHorizontal: 20,
    marginBottom: 10,
    borderRadius: 10,
  },
});

export default TaskItem;
Enter fullscreen mode Exit fullscreen mode

Update your App.js to include the ToDoList component:

import 'react-native-gesture-handler';
import 'react-native-reanimated';
import React from 'react';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import ToDoList from './ToDoList';

export default function App() {
  return (
    <GestureHandlerRootView style={{ flex: 1 }}>
      <ToDoList />
    </GestureHandlerRootView>
  );
}
Enter fullscreen mode Exit fullscreen mode

Running the Project

To run the project, use the following commands based on the platform you want to test:

Start the Expo development server:

  yarn start --reset-cache
Enter fullscreen mode Exit fullscreen mode

This will give you options to choose the platform, or you can

Directly Start Run on iOS:

  yarn ios
Enter fullscreen mode Exit fullscreen mode

Directly Start Run on Android:

  yarn android
Enter fullscreen mode Exit fullscreen mode

🫠 Now try to add tasks and swipe to the left to delete and you’ll see some cool animations!🧙🏻‍♂️


Conclusion

Reanimated 3 provides a powerful and efficient way to create high-performance animations in React Native. By running animations on the UI thread and offering a declarative API, Reanimated 3 ensures smooth and responsive animations, even under heavy load. In this tutorial, we built an animated to-do list app that allows users to add, remove, and reorder tasks with smooth animations. Start experimenting with Reanimated 3 today and take your React Native app’s user experience to the next level!


Next Steps

For an additional challenge, try implementing the ability to reorder tasks within the to-do list. Share your results and any issues you encounter!


🫠 Did you enjoy this article? Then please visit DevToys.io and subscribe to our newsletter so you can stay connected with all the latest dev news, tools and gadgets! ❤️

Top comments (0)