0
# Switch Transitions
1
2
The SwitchTransition component controls transitions between two states with different sequencing modes, inspired by Vue.js transition modes. It's ideal for switching between different components or states with controlled timing.
3
4
## Capabilities
5
6
### SwitchTransition Component
7
8
Controls the render timing between state transitions with configurable sequencing modes.
9
10
```javascript { .api }
11
/**
12
* Controls transitions between two states with different sequencing modes
13
* @param props - SwitchTransition props
14
* @returns JSX element managing component switching transitions
15
*/
16
function SwitchTransition({
17
mode,
18
children
19
}): JSX.Element;
20
21
interface SwitchTransitionProps {
22
/**
23
* Transition mode controlling sequence timing
24
* 'out-in': Current element exits first, then new element enters
25
* 'in-out': New element enters first, then current element exits
26
*/
27
mode?: 'out-in' | 'in-out';
28
/** Single Transition or CSSTransition component */
29
children: React.ReactElement;
30
}
31
```
32
33
### Mode Constants
34
35
Pre-defined mode constants for transition sequencing.
36
37
```javascript { .api }
38
/** Mode constants for SwitchTransition */
39
export const modes = {
40
/** Current element transitions out first, then new element transitions in */
41
out: 'out-in',
42
/** New element transitions in first, then current element transitions out */
43
in: 'in-out'
44
};
45
```
46
47
**Usage Examples:**
48
49
```javascript
50
import React, { useState } from 'react';
51
import { SwitchTransition, CSSTransition } from 'react-transition-group';
52
import './switch.css';
53
54
function SwitchExample() {
55
const [state, setState] = useState(false);
56
57
return (
58
<SwitchTransition mode="out-in">
59
<CSSTransition
60
key={state ? "goodbye" : "hello"}
61
addEndListener={(node, done) => {
62
node.addEventListener("transitionend", done, false);
63
}}
64
classNames='fade'
65
>
66
<button onClick={() => setState(state => !state)}>
67
{state ? "Goodbye, world!" : "Hello, world!"}
68
</button>
69
</CSSTransition>
70
</SwitchTransition>
71
);
72
}
73
74
// Image carousel with smooth transitions
75
function ImageCarousel() {
76
const [currentImage, setCurrentImage] = useState(0);
77
const images = ['image1.jpg', 'image2.jpg', 'image3.jpg'];
78
79
return (
80
<div className="carousel">
81
<SwitchTransition mode="out-in">
82
<CSSTransition
83
key={currentImage}
84
timeout={300}
85
classNames="slide"
86
>
87
<img
88
src={images[currentImage]}
89
alt={`Slide ${currentImage + 1}`}
90
className="carousel-image"
91
/>
92
</CSSTransition>
93
</SwitchTransition>
94
95
<button
96
onClick={() => setCurrentImage((currentImage + 1) % images.length)}
97
>
98
Next
99
</button>
100
</div>
101
);
102
}
103
```
104
105
### Transition Modes
106
107
**Out-In Mode (`'out-in'`):**
108
- Current element starts exiting
109
- Waits for exit to complete
110
- New element starts entering
111
- Prevents overlapping content during transition
112
113
**In-Out Mode (`'in-out'`):**
114
- New element starts entering immediately
115
- Current and new elements exist simultaneously
116
- Current element starts exiting after new element enters
117
- Allows for crossfade effects and overlapping animations
118
119
```javascript
120
function ModeComparison() {
121
const [content, setContent] = useState('first');
122
const [mode, setMode] = useState('out-in');
123
124
return (
125
<div>
126
<div>
127
<label>
128
<input
129
type="radio"
130
checked={mode === 'out-in'}
131
onChange={() => setMode('out-in')}
132
/>
133
Out-In (sequential)
134
</label>
135
<label>
136
<input
137
type="radio"
138
checked={mode === 'in-out'}
139
onChange={() => setMode('in-out')}
140
/>
141
In-Out (overlapping)
142
</label>
143
</div>
144
145
<SwitchTransition mode={mode}>
146
<CSSTransition
147
key={content}
148
timeout={500}
149
classNames="switch"
150
>
151
<div className="content-box">
152
{content === 'first' ? 'First Content' : 'Second Content'}
153
</div>
154
</CSSTransition>
155
</SwitchTransition>
156
157
<button onClick={() => setContent(content === 'first' ? 'second' : 'first')}>
158
Switch Content
159
</button>
160
</div>
161
);
162
}
163
```
164
165
### Route Transitions
166
167
SwitchTransition works well for page/route transitions:
168
169
```javascript
170
import { useLocation } from 'react-router-dom';
171
172
function RouteTransition({ children }) {
173
const location = useLocation();
174
175
return (
176
<SwitchTransition mode="out-in">
177
<CSSTransition
178
key={location.pathname}
179
timeout={300}
180
classNames="page"
181
>
182
<div className="page-container">
183
{children}
184
</div>
185
</CSSTransition>
186
</SwitchTransition>
187
);
188
}
189
190
// Usage with router
191
function App() {
192
return (
193
<Router>
194
<RouteTransition>
195
<Routes>
196
<Route path="/" element={<Home />} />
197
<Route path="/about" element={<About />} />
198
<Route path="/contact" element={<Contact />} />
199
</Routes>
200
</RouteTransition>
201
</Router>
202
);
203
}
204
```
205
206
### Key-Based Switching
207
208
SwitchTransition uses the `key` prop to determine when to switch:
209
210
```javascript
211
// ✅ Correct - key changes trigger transitions
212
<SwitchTransition>
213
<CSSTransition
214
key={currentState} // Key changes when state changes
215
timeout={200}
216
classNames="switch"
217
>
218
<div>{currentState}</div>
219
</CSSTransition>
220
</SwitchTransition>
221
222
// ❌ Incorrect - static key won't trigger transitions
223
<SwitchTransition>
224
<CSSTransition
225
key="static" // Key never changes
226
timeout={200}
227
classNames="switch"
228
>
229
<div>{currentState}</div>
230
</CSSTransition>
231
</SwitchTransition>
232
```
233
234
### Example CSS for Switch Transitions
235
236
```css
237
/* Fade transition for out-in mode */
238
.fade-enter {
239
opacity: 0;
240
}
241
242
.fade-enter-active {
243
opacity: 1;
244
transition: opacity 300ms ease-in-out;
245
}
246
247
.fade-exit {
248
opacity: 1;
249
}
250
251
.fade-exit-active {
252
opacity: 0;
253
transition: opacity 300ms ease-in-out;
254
}
255
256
/* Slide transition for route changes */
257
.page-enter {
258
transform: translateX(100%);
259
}
260
261
.page-enter-active {
262
transform: translateX(0);
263
transition: transform 300ms ease-out;
264
}
265
266
.page-exit {
267
transform: translateX(0);
268
}
269
270
.page-exit-active {
271
transform: translateX(-100%);
272
transition: transform 300ms ease-in;
273
}
274
275
/* Scale transition for in-out mode */
276
.scale-enter {
277
transform: scale(0.8);
278
opacity: 0;
279
}
280
281
.scale-enter-active {
282
transform: scale(1);
283
opacity: 1;
284
transition: all 400ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
285
}
286
287
.scale-exit {
288
transform: scale(1);
289
opacity: 1;
290
}
291
292
.scale-exit-active {
293
transform: scale(1.1);
294
opacity: 0;
295
transition: all 300ms ease-in;
296
}
297
```
298
299
### Lifecycle Callback Integration
300
301
SwitchTransition preserves and calls lifecycle callbacks from child components:
302
303
```javascript
304
function CallbackExample() {
305
const [key, setKey] = useState('a');
306
307
return (
308
<SwitchTransition>
309
<CSSTransition
310
key={key}
311
timeout={300}
312
classNames="switch"
313
onEnter={() => console.log('Entering:', key)}
314
onExit={() => console.log('Exiting:', key)}
315
>
316
<div>Content {key}</div>
317
</CSSTransition>
318
</SwitchTransition>
319
);
320
}
321
```