0
# Transition Groups
1
2
The TransitionGroup component manages a set of transition components in a list, automatically coordinating the mounting and unmounting of items with proper transition timing.
3
4
## Capabilities
5
6
### TransitionGroup Component
7
8
Manages transitions for dynamic lists of components, handling enter and exit animations for list items.
9
10
```javascript { .api }
11
/**
12
* Manages a set of transition components in a list with automatic coordination
13
* @param props - TransitionGroup props
14
* @returns JSX element containing managed transition children
15
*/
16
function TransitionGroup({
17
component,
18
children,
19
appear,
20
enter,
21
exit,
22
childFactory,
23
...otherProps
24
}): JSX.Element;
25
26
interface TransitionGroupProps {
27
/** Component to render as container (default: 'div', use null for no wrapper) */
28
component?: React.ComponentType<any> | string | null;
29
/** Set of Transition or CSSTransition components to manage */
30
children?: React.ReactNode;
31
/** Enable/disable appear animations for all children */
32
appear?: boolean;
33
/** Enable/disable enter animations for all children */
34
enter?: boolean;
35
/** Enable/disable exit animations for all children */
36
exit?: boolean;
37
/** Function to wrap every child, including exiting ones */
38
childFactory?: (child: React.ReactElement) => React.ReactElement;
39
}
40
```
41
42
**Usage Examples:**
43
44
```javascript
45
import React, { useState } from 'react';
46
import { TransitionGroup, CSSTransition } from 'react-transition-group';
47
import './list.css';
48
49
function TodoList() {
50
const [items, setItems] = useState([
51
{ id: 1, text: 'Buy milk' },
52
{ id: 2, text: 'Walk dog' },
53
{ id: 3, text: 'Write code' }
54
]);
55
56
const addItem = () => {
57
const newItem = {
58
id: Date.now(),
59
text: `Item ${items.length + 1}`
60
};
61
setItems([...items, newItem]);
62
};
63
64
const removeItem = (id) => {
65
setItems(items.filter(item => item.id !== id));
66
};
67
68
return (
69
<div>
70
<TransitionGroup component="ul" className="todo-list">
71
{items.map(item => (
72
<CSSTransition
73
key={item.id}
74
timeout={300}
75
classNames="item"
76
>
77
<li onClick={() => removeItem(item.id)}>
78
{item.text}
79
</li>
80
</CSSTransition>
81
))}
82
</TransitionGroup>
83
<button onClick={addItem}>Add Item</button>
84
</div>
85
);
86
}
87
88
// Without wrapper element
89
function NoWrapperGroup({ items }) {
90
return (
91
<TransitionGroup component={null}>
92
{items.map(item => (
93
<CSSTransition
94
key={item.id}
95
timeout={200}
96
classNames="fade"
97
>
98
<div className="item">{item.text}</div>
99
</CSSTransition>
100
))}
101
</TransitionGroup>
102
);
103
}
104
```
105
106
### Child Factory Function
107
108
The `childFactory` prop allows modification of children, including those that are exiting:
109
110
```javascript { .api }
111
/**
112
* Child factory function for modifying transition children
113
* @param child - React element being managed by TransitionGroup
114
* @returns Modified React element
115
*/
116
type ChildFactory = (child: React.ReactElement) => React.ReactElement;
117
```
118
119
**Usage Example:**
120
121
```javascript
122
function DynamicTransitionGroup({ items, fastExit }) {
123
const childFactory = (child) => {
124
// Modify exiting children to use faster animation
125
return React.cloneElement(child, {
126
timeout: fastExit ? 100 : 300,
127
classNames: fastExit ? 'fast-exit' : 'normal'
128
});
129
};
130
131
return (
132
<TransitionGroup childFactory={childFactory}>
133
{items.map(item => (
134
<CSSTransition
135
key={item.id}
136
timeout={300}
137
classNames="normal"
138
>
139
<div>{item.text}</div>
140
</CSSTransition>
141
))}
142
</TransitionGroup>
143
);
144
}
145
```
146
147
### List Animation Patterns
148
149
Common patterns for animating lists with TransitionGroup:
150
151
**Staggered Animations:**
152
```javascript
153
function StaggeredList({ items }) {
154
return (
155
<TransitionGroup component="div" className="staggered-list">
156
{items.map((item, index) => (
157
<CSSTransition
158
key={item.id}
159
timeout={300}
160
classNames="stagger"
161
style={{ animationDelay: `${index * 50}ms` }}
162
>
163
<div className="list-item">
164
{item.text}
165
</div>
166
</CSSTransition>
167
))}
168
</TransitionGroup>
169
);
170
}
171
```
172
173
**Complex List Operations:**
174
```javascript
175
function AdvancedList() {
176
const [items, setItems] = useState([]);
177
178
const handleReorder = (fromIndex, toIndex) => {
179
const newItems = [...items];
180
const [removed] = newItems.splice(fromIndex, 1);
181
newItems.splice(toIndex, 0, removed);
182
setItems(newItems);
183
};
184
185
return (
186
<TransitionGroup component="div">
187
{items.map(item => (
188
<CSSTransition
189
key={item.id}
190
timeout={{ enter: 300, exit: 200 }}
191
classNames="list-item"
192
>
193
<div
194
className="draggable-item"
195
onDragEnd={(e) => handleReorder(...)}
196
>
197
{item.text}
198
</div>
199
</CSSTransition>
200
))}
201
</TransitionGroup>
202
);
203
}
204
```
205
206
### TransitionGroup Behavior
207
208
TransitionGroup automatically:
209
210
1. **Tracks children by key**: Uses React keys to identify which items are entering, staying, or leaving
211
2. **Manages transition props**: Automatically sets `in` prop to `true` for entering items and `false` for exiting items
212
3. **Handles exit cleanup**: Removes components from DOM after exit transition completes
213
4. **Coordinates timing**: Ensures proper sequencing of enter/exit animations
214
215
### Key Requirements
216
217
All children of TransitionGroup must have unique `key` props:
218
219
```javascript
220
// ✅ Correct - each child has unique key
221
<TransitionGroup>
222
{items.map(item => (
223
<CSSTransition key={item.id} timeout={200} classNames="fade">
224
<div>{item.text}</div>
225
</CSSTransition>
226
))}
227
</TransitionGroup>
228
229
// ❌ Incorrect - missing or duplicate keys will cause issues
230
<TransitionGroup>
231
{items.map(item => (
232
<CSSTransition timeout={200} classNames="fade">
233
<div>{item.text}</div>
234
</CSSTransition>
235
))}
236
</TransitionGroup>
237
```
238
239
### Example CSS for List Animations
240
241
```css
242
/* Slide in from right, slide out to left */
243
.item-enter {
244
transform: translateX(100%);
245
opacity: 0;
246
}
247
248
.item-enter-active {
249
transform: translateX(0);
250
opacity: 1;
251
transition: all 300ms ease-out;
252
}
253
254
.item-exit {
255
transform: translateX(0);
256
opacity: 1;
257
}
258
259
.item-exit-active {
260
transform: translateX(-100%);
261
opacity: 0;
262
transition: all 200ms ease-in;
263
}
264
265
/* Scale and fade */
266
.scale-enter {
267
transform: scale(0.8);
268
opacity: 0;
269
}
270
271
.scale-enter-active {
272
transform: scale(1);
273
opacity: 1;
274
transition: all 250ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
275
}
276
277
.scale-exit {
278
transform: scale(1);
279
opacity: 1;
280
}
281
282
.scale-exit-active {
283
transform: scale(0.8);
284
opacity: 0;
285
transition: all 150ms ease-in;
286
}
287
```