# List Animation

## [TransitionGroup](http://reactcommunity.org/react-transition-group/transition-group)

The `<TransitionGroup>` component manages a set of transition components (`<Transition>` and `<CSSTransition>`) in a list. Like with the transition components, `<TransitionGroup>` is a state machine for managing the mounting and unmounting of components over time.

Note that `<TransitionGroup>` does not define any animation behavior! Exactly *how* a list item animates is up to the individual transition component. This means you can mix and match animations across different list items.

## [Props](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-props)

### [component](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-component)

`<TransitionGroup>` renders a `<div>` by default. You can change this behavior by providing a `component` prop. If you use React v16+ and would like to avoid a wrapping `<div>` element you can pass in `component={null}`. This is useful if the wrapping div borks your css styles.

**type**: `any`

**default**: `'div'`

### [enter](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-enter)

A convenience prop that enables or disables enter animations for all children. Note that specifying this will override any defaults set on individual children Transitions.

**type**: `boolean`

### [exit](http://reactcommunity.org/react-transition-group/transition-group#TransitionGroup-prop-exit)

A convenience prop that enables or disables exit animations for all children. Note that specifying this will override any defaults set on individual children Transitions.

**type**: `boolean`

## Example

Let's make a list of numbers which we can add and remove based on click handlers.

{% tabs %}
{% tab title="List Component" %}
{% code title="components/List.js" %}

```jsx
import {useState} from 'react';

import classes from "./List.module.css";

const List = () => {
  const [data, setData] = useState({
    items: [1, 2, 3]
  });

  const addItemHandler = () => {
    setData((prevState) => {
      let value = 1;
      if (prevState.items.length > 0) {
        value = prevState.items[prevState.items.length - 1] + 1;
      }
      return {
        items: prevState.items.concat(value)
      };
    });
  };
  const removeItemHandler = (idx) => {
    setData((prevState) => {
      return {
        items: prevState.items.filter((item, index) => index !== idx)
      };
    });
  };

  let listContent;
  if (data.items.length === 0) {
    listContent = <p>Please add items!</p>;
  } else {
    listContent = data.items.map((item, index) => (
      <li
        key={index}
        className={classes.listitem}
        onClick={removeItemHandler.bind(null, index)}
      >
        {item}
      </li>
    ));
  }

  return (
    <div className={classes.container}>
      <button className="button" onClick={addItemHandler}>
        Add Item
      </button>
      <p>Click to remove the item.</p>
      <ul className={classes.list}>{listContent}</ul>
    </div>
  );
};

export default List;
```

{% endcode %}
{% endtab %}

{% tab title="List Styles" %}

```css
.container {
  margin: 5px auto;
}

.list {
  list-style: none;
  text-align: center;
  margin: 0 auto;
  padding: 0;
  width: 280px;
}

.listitem {
  box-sizing: border-box;
  border: 1px solid green;
  padding: 10px;
  width: 100%;
  margin: 0 auto;
  border-radius: 5px;
  margin-bottom: 0.5rem;
}

.listitem:hover,
.listitem:active {
  cursor: pointer;
  background-color: #ccc;
}

```

{% endtab %}
{% endtabs %}

Since the `<TransitionGroup>` component does not define any animation behavior, we will use the `<CSSTransition>` component to define the animations in our list items!

The important thing here is,  we are not going to use the `in` property to control the state of our transition. The special thing about `<TransitionGroup>` is that it is able to handle multiple items, and is able to determine whenever one element changes, i.e, if it is removed or added. It will then manually set the `in` property on the wrapped `<Transition>` or `<CSSTransition>`component. We cannot control the `in` property for a dynamic list, hence `<TransitionGroup>` does that for us out of the box.

### Code snippet

{% tabs %}
{% tab title="List Component" %}
{% code title="components/List.js" %}

```jsx
//...
import TransitionGroup from 'react-transition-group/TransitionGroup';
import CSSTransition from 'react-transition-group/CSSTransition';

const List = () => {
  //...
  const listItem = listArr.items.map((item, index) => (
    <CSSTransition
      key={index}
      timeout={200}
      classNames={{
        enter: classes['fade-enter'],
        enterActive: classes['fade-enter-active'],
        exit: classes['fade-exit'],
        exitActive: classes['fade-exit-active'],
      }}
    >
      <li
        className={classes.ListItem}
        onClick={removeItemHandler.bind(null, index)}
      >
        {item}
      </li>
    </CSSTransition>
  ));
  
  return (
    <div>
      <button className="button" onClick={addItemHandler}>
        Add Item
      </button>
      <p>Click to remove the item.</p>
      <TransitionGroup component="ul" className={classes.List}>
        {listItems}
      </TransitionGroup>
    </div>
  );
}

export default List;
```

{% endcode %}
{% endtab %}

{% tab title="List Styles" %}
{% code title="components/List.module.ss" %}

```css
/*
* ...
*/

.fade-enter {
  opacity: 0;
}

.fade-enter-active {
  opacity: 1;
  transition: opacity 0.3s ease-out;
}

.fade-exit {
  opacity: 1;
}
.fade-exit-active {
  opacity: 0;
  transition: opacity 0.3s ease-out;
}
```

{% endcode %}
{% endtab %}
{% endtabs %}

The final code example can be found [here at codesandbox.io](https://codesandbox.io/s/react-transition-group-x4coq?file=/src/App.js).

## Alternatives

There are a few popular alternatives to `react-transition-group` for animating a React app:

* [react-motion](https://github.com/chenglou/react-motion): for emulating real-world physics \[not actively maintained]
* [react-move](https://react-move.js.org/#/): for complex animations
* [react-router-transition](https://github.com/maisano/react-router-transition): for animating routing and routes on switch, but has limitations.

To use `react-transition-group` for route animations, refer to [this example](http://reactcommunity.org/react-transition-group/with-react-router/).

All of them are open-sourced, and have their own docs, if you would like to explore them.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://sydrawat.gitbook.io/react/miscellaneous/animations-in-react/animating-lists.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
