Animate React components with a single line using AutoAnimate
Tags: react, webdev
Published: 2022-11-29 20:28:52

**Written by [Nilanth Sriram](https://blog.logrocket.com/author/nilanthsriram/)✏️**

Animation provides a compelling user experience for modern web apps, bringing them to life and avoiding that dreaded flat look. But, of course, adding animations can be a difficult and time-consuming task, and if your app has multiple components, it gets worse! 

In this article, we‘re going to be taking a look at how you can add animation to React components with a single line of code using the AutoAnimate library. 

Let’s get straight into it. 

_Jump ahead:_

*   [What is AutoAnimate?](#autoanimate)
*   [Why not use other animation libraries?](#other-animation-libraries)
*   [Alert message using React Transition Group](#alert-message-react-transition-group)
*   [Alert message using AutoAnimate](#alert-message-autoanimate)
*   [How does it work?](#how-does-it-work)
*   [Quick setup and usage](#quick-setup-usage)
*   [Animate a dynamic `Form` component](#animate-dynamic-form-component)
*   [Animate a user comment component](#animate-user-comment-component)
*   [Customize the animation duration](#customize-animation-duration)
*   [Enable and disable animations](#enable-disable-animations)

## What is AutoAnimate? <a name="autoanimate">

AutoAnimate is an open-source animation utility library with zero configuration that adds smooth transitions to React components while also being very [lightweight](https://bundlephobia.com/package/@formkit/auto-animate@1.0.0-beta.3) (2.3KB).

## Why not use other animation libraries? <a name="other-animation-libraries">

Most animation libraries require more configuration, and some require changing the existing component structure to apply animations. 

AutoAnimate, however, requires only a single line of code to animate components and does not require changing any existing components. It also offers the benefit of being straightforward to integrate with an existing code base. 

AutoAnimate makes for a smooth experience when an element changes in the DOM. I would like to compare AutoAnimate with [React Transition Group](https://reactcommunity.org/react-transition-group/), which is a simple transition library for component entering and exiting, but with some additional configurations. 

Let’s create an alert message with React Transition Group and AutoAnimate so you can see the difference between the libraries for yourself.

## Alert message using React Transition Group <a name="alert-message-react-transition-group">

The following component shows how to add animation [using](https://blog.logrocket.com/react-transition-group/) React Transition Group.

```javascript
App.jsx
import React, { useState, useRef } from 'react';
import { createRoot } from 'react-dom/client';
import { Container, Button, Alert } from 'react-bootstrap';
import { CSSTransition } from 'react-transition-group';

import 'bootstrap/dist/css/bootstrap.min.css';
import './styles.css';

function Example() {
  const [showButton, setShowButton] = useState(true);
  const [showMessage, setShowMessage] = useState(false);
  const nodeRef = useRef(null);

  return (
    <Container style={{ paddingTop: '2rem' }}>
      {showButton && (
        <Button
          onClick={() => setShowMessage(true)}
          size="lg"
        >
          Show Message
        </Button>
      )}
      <CSSTransition
        in={showMessage}
        nodeRef={nodeRef}
        timeout={300}
        classNames="alert"
        unmountOnExit
        onExited={() => setShowButton(true)}
      >
        <Alert
          ref={nodeRef}
          variant="primary"
          dismissible
          onClose={() => setShowMessage(false)}
        >
          <Alert.Heading>
            Animated alert message
          </Alert.Heading>
          <p>
            This alert message is being transitioned in and
            out of the DOM.
          </p>
          <Button
            variant="primary"
            onClick={() => setShowMessage(false)}
          >
            Close
          </Button>
        </Alert>
      </CSSTransition>
    </Container>
  );
}
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Example />);
```

Add the following styles to add the transition:

```javascript
//styles.css
.alert-enter {
  opacity: 0;
  transform: scale(0.9);
}
.alert-enter-active {
  opacity: 1;
  transform: translateX(0);
  transition: opacity 300ms, transform 300ms;
}
.alert-exit {
  opacity: 1;
}
.alert-exit-active {
  opacity: 0;
  transform: scale(0.9);
  transition: opacity 300ms, transform 300ms;
}
```

The above code will produce the following output: ![Alert Message React Transition Group.](https://blog.logrocket.com/wp-content/uploads/2022/11/alert-message-react-transition-group.gif) 

To add this transition, we have added a few lines of CSS and passed a few props to the CSS `transition` component. 

Now, let’s reproduce the same animation using AutoAnimate with zero configuration.

> **N.B.**, you can find the above demo here at [CodeSandbox](https://codesandbox.io/s/react-transition-group-th033h?file=/index.js)

## Alert message using AutoAnimate <a name="alert-message-autoanimate">

The following component shows you how to add an animation using AutoAnimate.

```javascript
//App.jsx

import React, { useState, useRef } from 'react';
import { createRoot } from 'react-dom/client';
import { Container, Button, Alert } from 'react-bootstrap';
import { useAutoAnimate } from '@formkit/auto-animate/react';

import 'bootstrap/dist/css/bootstrap.min.css';

function Example() {
//Auto Animate
  const [parent] = useAutoAnimate(/* optional config */);

  const [showButton, setShowButton] = useState(true);
  const [showMessage, setShowMessage] = useState(false);
  const nodeRef = useRef(null);

  return (
    <Container style={{ paddingTop: '2rem' }}>
      {showButton && (
        <Button
          onClick={() => setShowMessage(true)}
          size="lg"
        >
          Show Message
        </Button>
      )}
      <div ref={parent}>
        {showMessage && (
          <Alert
            ref={nodeRef}
            variant="primary"
            dismissible
            onClose={() => setShowMessage(false)}
          >
            <Alert.Heading>
              Animated alert message
            </Alert.Heading>
            <p>
              This alert message is being transitioned in
              and out of the DOM.
            </p>
            <Button
              variant="primary"
              onClick={() => setShowMessage(false)}
            >
              Close
            </Button>
          </Alert>
        )}
      </div>
    </Container>
  );
}
const container = document.getElementById('root');
const root = createRoot(container);
root.render(<Example />);
```

Here, we have used the same code that we used for React Transition Group. We have included the AutoAnimate library and added the `useAutoAnimate` hook ref to the `Alert` `parent` element (`<div>`). 

That's all we need to do! It’s not necessary for us to add the CSS or transition duration. Let’s see the output here: ![AutoAnimate Alert Message](https://blog.logrocket.com/wp-content/uploads/2022/11/autoanimate-alert-message.gif) 

We can see here that we’ve created the same animation with zero configuration — this is how AutoAnimate differs from other libraries!

> **N.B.**, you can find the above demo here at [CodeSandbox](https://codesandbox.io/s/auto-animate-dffre9?file=/index.js)

## How does it work?

AutoAnimate is a single-function utility that accepts a parent element of the component which needs to be animated. The animation is then applied to the immediate child elements of the parent element. 

AutoAnimate triggers the animations when the following events occur:

*   A child element is inserted into the DOM
*   A child element is removed from the DOM
*   A child element is moved in the DOM

## Quick setup and usage <a name="quick-setup-usage">

Now, let’s set up AutoAnimate for use in your projects. 

Install AutoAnimate using the following command: `yarn add @formkit/auto-animate` 

Import the `useAutoAnimate` hooks into the component which you want to animate, as shown here: 

`import { useAutoAnimate } from '@formkit/auto-animate/react` 

To animate a component, we need to add the reference returned by the `useAutoAnimate` hook to the parent element, as seen here:

```javascript
//App.jsx

import { useState } from 'react'
import { useAutoAnimate } from '@formkit/auto-animate/react'

const App = function () {
  const [items, setItems] = useState([0, 1, 2])
  const [parent] = useAutoAnimate()
  const add = () => setItems([...items, items.length])
  return 
  <>
  <ul ref={parent}>
    {items.map(
      item => <li key={item}>{ item }</li>
    )}
  </ul>
  <button onClick={add}>Add number</button>
  </>
}

export default App
```

Here, we have passed the reference of the parent element `<ul>` to `useAutoAnimate`. When clicking the **Add Number** button, the newly added list will be animated. 

Next, we will take a look at some more examples.

## Animate a dynamic `Form` component <a name="animate-dynamic-form-component">

Most apps have dynamic input `Form` components. Now, we will create a dynamic component, so add the following code:

> **N.B.**, I have used the Ant Design `Form` for the sake of simplicity for this walkthrough

```javascript
//DynamicForm.jsx

import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { Button, Form, Input, Space } from 'antd';
import React from 'react';

const DynamicForm = () => {
    return (
            <Form name="dynamic_form_nest_item" autoComplete="off" >
                <Form.List name="users">
                    {(fields, { add, remove }) => (
                        <div>
                            {fields.map(({ key, name, ...restField }) => (
                                <Space
                                    key={key}
                                    style={{
                                        display: 'flex',
                                        marginBottom: 8,
                                    }}
                                    align="baseline"
                                >
                                    <Form.Item
                                        {...restField}
                                        name={[name, 'first']}
                                        rules={[
                                            {
                                                required: true,
                                                message: 'Missing first name',
                                            },
                                        ]}
                                    >
                                        <Input placeholder="First Name" />
                                    </Form.Item>
                                    <Form.Item
                                        {...restField}
                                        name={[name, 'last']}
                                        rules={[
                                            {
                                                required: true,
                                                message: 'Missing last name',
                                            },
                                        ]}
                                    >
                                        <Input placeholder="Last Name" />
                                    </Form.Item>
                                    <MinusCircleOutlined 
                                      onClick={() => remove(name)} 
                                      />
                                </Space>
                            ))}
                            <Form.Item>
                                <Button 
                                    type="dashed" 
                                    onClick={() => add()} 
                                    block 
                                    icon={<PlusOutlined/>
                                    }>
                                    Add field
                                </Button>
                            </Form.Item>
                        </div>
                    )}
                </Form.List>
            </Form>
    );
};

export default DynamicForm;
```

Now, we will see the following output when we run the component. When we click on **Add field,** the inputs are added in a fraction of a second; it feels like bad UX to me! ![React Without AutoAnimate ](https://blog.logrocket.com/wp-content/uploads/2022/11/react-without-autoanimate.gif) 

Let’s animate the form with AutoAnimate using a single line. Import the AutoAnimate library using the code in the `DynamicForm` component: 

`import { useAutoAnimate } from '@formkit/auto-animate/react'` 

Next, add the `useAutoAnimate` hook, as demonstrated here: 

`const [parent] = useAutoAnimate(/* optional config */)` 

Then, pass the reference for the parent element `<div>`, as below: 

`<div ref={parent}>` 

Now, run the code again; you can see the magic of AutoAnimate in action! ![AutoAnimate Example](https://blog.logrocket.com/wp-content/uploads/2022/11/auto-animate-examples.gif)

## Animate a user comment component <a name="animate-user-comment-component">

Another use case is to auto-animate the `Comments` component of an application. 

Here, we are developing a `Comments` component, which is used to add comments to a post. If a new comment is added, it is displayed at the top of a list.

```javascript
//Comments.jsx
import {Avatar, Button, Comment, Form, Input,} from 'antd';
import React, {useState} from 'react';
import {useAutoAnimate} from '@formkit/auto-animate/react'
const {TextArea} = Input;

const Editor = ({onChange, onSubmit, submitting, value}) => (
    <>
        <Form.Item>
            <TextArea rows={4} onChange={onChange} value={value}/>
        </Form.Item>
        <Form.Item>
            <Button 
                htmlType="submit" 
                loading={submitting} 
                onClick={onSubmit} 
                type="primary"
                >
            Add Comment
            </Button>
        </Form.Item>
    </>
);

const Comments = () => {
    const [comments, setComments] = useState([]);
    const [submitting, setSubmitting] = useState(false);
    const [value, setValue] = useState('');
    const [parent] = useAutoAnimate()
    const handleSubmit = () => {
        if (!value) return;
        setSubmitting(true);
        setTimeout(() => {
            setSubmitting(false);
            setValue('');
            setComments([
                ...comments,
                {
                    author: 'Han Solo',
                    avatar: 'https://joeschmoe.io/api/v1/random',
                    content: <p>{value}</p>,
                },
            ]);
        }, 500);
    };

    const handleChange = (e) => {
        setValue(e.target.value);
    };

    return (
        <>
            <ul ref={parent}>
                {comments.map((comment) => (
                        <Comment
                            key={comment.content}
                            author={comment.author}
                            avatar={
                                    <Avatar 
                                      src="https://joeschmoe.io/api/v1/random" 
                                      alt="Han Solo"
                                    />
                                    }
                            content={
                                <p>
                                    {comment.content}
                                </p>
                            }
                        />
                    )
                )}
            </ul>
            <Comment
                avatar={
                  <Avatar src="https://joeschmoe.io/api/v1/random" alt="Han Solo"/>
                }
                content={
                    <Editor
                        onChange={handleChange}
                        onSubmit={handleSubmit}
                        submitting={submitting}
                        value={value}
                    />
                }
            />
        </>
    );
};

export default Comments;
```

In the above example, we have a comment input. When the user types a comment and clicks **Add Comment****,** the entered comment is appended at the top with an animation. To animate the list, we have added an AutoAnimate hook reference to the `<ul>` element. 

Now, we will see the following output when we run the component: ![User Comment Component.](https://blog.logrocket.com/wp-content/uploads/2022/11/user-comment-component.gif)

## Customize the animation duration <a name="customize-animation-duration">

We can customize the transition time by passing the `duration` props to `useAutoAnimate`. Let's see this in action with a dynamic card as an example. 

In this example, we made the transition 500ms long, so when the user clicks **Add Task**, a new card is inserted and all other cards are moved after 500ms.

```javascript
//DynamicComponents.jsx

import React, {useState} from "react";
import {Avatar, Button, Card, Col, Form, Input, Row} from 'antd';
import {useAutoAnimate} from "@formkit/auto-animate/react";

const {Meta} = Card;

export default function DynamicComponents() {

    const [comments, setComments] = useState([]);
    const [parent] = useAutoAnimate({duration: 500});

    const handleSubmit = (values) => {
        if (!values) return;
        setComments((prev) => [{content: values.content}, ...prev]);
    };

    return (
        <>
            <Form
                name="basic"
                onFinish={handleSubmit}
                autoComplete="off"
            >
                <Form.Item
                    name="content"
                >
                   <Input/>
                </Form.Item>
                <Form.Item>
                    <Button htmlType="submit" type="primary">
                        Add Task
                    </Button>
                </Form.Item>
            </Form>
            <Row gutter={[16, 24]} ref={parent}>
                {comments.map((comment) => (
                    <Col span={6} key={comment.content}>
                        <Card
                            style={{
                                width: 100,
                            }}
                            cover={
                                <img
                                    alt="example"
                                    src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
                                />
                            }
                        >
                            <Meta
                                avatar={
                                <Avatar src="https://joeschmoe.io/api/v1/random"/>
                                  }
                                description={comment.content}
                            />
                        </Card>
                    </Col>
                ))
                }
            </Row>
        </>
    );
}
```

Now, we will see the following output when we run the component: ![Customize Animation Duration.](https://blog.logrocket.com/wp-content/uploads/2022/11/customize-animation-duration.gif)

## Enable and disable animations <a name="enable-disable-animations">

Sometimes, we are required to disable an animation and use it later. To handle these cases, the AutoAnimate hook `useAutoAnimate` returns the **Enable** and **Disable** functions, which can be used to enable and disable an animation. 

We can see this in the following code block:

```javascript
//DynamicCards.jsx

import React, {useState} from "react";
import {Avatar, Button, Card, Col, Form, Input, Row} from 'antd';
import {useAutoAnimate} from "@formkit/auto-animate/react";

const {Meta} = Card;

export default function DynamicCards() {
    const [comments, setComments] = useState([]);
    const [parent, enable] = useAutoAnimate({duration: 500});
    const [isEnabled, setIsEnabled] = useState(true)

    const handleSubmit = (values) => {
        if (!values) return;
        setComments((prev) => [{content: values.content}, ...prev]);
    };

    function toggle () {
        enable(!isEnabled)
        setIsEnabled(!isEnabled)
    }

    return (
        <>
            <Form
                name="basic"
                onFinish={handleSubmit}
                autoComplete="off"
            >
                <Form.Item
                    name="content"
                >
                    <Input/>
                </Form.Item>
                <Form.Item>
                    <Button htmlType="submit" type="primary">
                        Add Task
                    </Button>
                </Form.Item>
                <Form.Item>
                    <Button onClick={toggle} type="primary">
                        { isEnabled ? "🚫 Disable" : "✅ Enable" } animations
                    </Button>
                </Form.Item>
            </Form>
            <Row gutter={[16, 24]} ref={parent}>
                {comments.map((comment) => (
                    <Col span={6} key={comment.content}>
                        <Card
                            style={{
                                width: 100,
                            }}
                            cover={
                                <img
                                    alt="example"
                                    src="https://gw.alipayobjects.com/zos/rmsportal/JiqGstEfoWAOHiTxclqi.png"
                                />
                            }
                        >
                            <Meta
                                avatar={
                                  <Avatar 
                                  src="https://joeschmoe.io/api/v1/random"/>}
                                  description={comment.content}
                            />
                        </Card>
                    </Col>
                ))
                }
            </Row>
        </>
    );
}
```

Here, we have used our previous example by adding enable and disable options to it. Animation is controlled by the `enable` boolean prop passed to the `useAutoAnimate` hook. 

Now, we will see the following output when we run the component: ![Enable And Disable Animations ](https://blog.logrocket.com/wp-content/uploads/2022/11/enable-disable-animations.gif) 

AutoAnimate is a zero-config utility that also provides an option to customize the default animation keyframes and use custom animations. However, AutoAnimate’s default animation offerings will typically be enough for most components in my experience.

> **N.B.**, note: You can find the complete code of this tutorial in this [CodeSandbox](https://codesandbox.io/s/auto-animate-amimation-examples-react-tfk9d2)

## Conclusion

AutoAnimate makes animation very simple with its zero-config approach, ease of use, and speedy implementation — it helps devs efficiently provide smooth user experiences in their projects. 

In addition to the examples we’ve looked at today with React, AutoAnimate also supports Vue, Angular, and Svelte. You can find examples of other JavaScript frameworks in the official [docs](https://auto-animate.formkit.com/#usage-vue). 

Let me know of your own experiences using AutoAnimate in the comments below and thanks for reading!

---
##Cut through the noise of traditional React error reporting with LogRocket

[LogRocket](https://lp.logrocket.com/blg/react-signup-issue-free) is a React analytics solution that shields you from the hundreds of false-positive errors alerts to just a few truly important items. LogRocket tells you the most impactful bugs and UX issues actually impacting users in your React applications.

[![LogRocket signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://lp.logrocket.com/blg/signup)

[LogRocket](https://lp.logrocket.com/blg/react-signup-issue-free) automatically aggregates client side errors, React error boundaries, Redux state, slow component load times, JS exceptions, frontend performance metrics, and user interactions. Then LogRocket uses machine learning to notify you of the most impactful problems affecting the most users and provides the context you need to fix it.

Focus on the React bugs that matter — [try LogRocket today](https://lp.logrocket.com/blg/react-signup-issue-free).