這篇要繼續介紹剩下的兩個元件。
主要是用來渲染兩個狀態間做切換的過渡動畫,假如想要讓新元素加入和舊元素移除同時發生時出現動畫,官方網站比較建議使用 TransitionGroup 元件。
SwitchTransition 元件有 props 屬性 mode,當值為:
在使用 SwitchTransition 元件時,裡面要有 CSSTransition 或者 Transition 元件,並且裡面的這兩種元件是透過 key 屬性去判斷狀態,而不是 in。
以下是官方提供的使用 SwitchTransition 元件的範例,不過只有片段的程式,透過閱讀可以看到 CSSTransition 用 key 去取得 state,並且被 SwitchTransition 元件包覆。
function App() {
const [state, setState] = useState(false);
return (
<SwitchTransition>
<CSSTransition
key={state ? "Goodbye, world!" : "Hello, world!"}
addEndListener={(node, done) => node.addEventListener("transitionend", done, false)}
classNames='fade'
>
<button onClick={() => setState(state => !state)}>
{state ? "Goodbye, world!" : "Hello, world!"}
</button>
</CSSTransition>
</SwitchTransition>
);
}
.fade-enter{
opacity: 0;
}
.fade-exit{
opacity: 1;
}
.fade-enter-active{
opacity: 1;
}
.fade-exit-active{
opacity: 0;
}
.fade-enter-active,
.fade-exit-active{
transition: opacity 500ms;
}
完整的範例在這個連結:
接著我們來做一個範例,每次轉換狀態 state 時都會出現不同的色塊:
用來管理多個 transition 元件,包括 <Transition>
和 <CSSTransition>
,將這些元件包覆後 in 這個屬性就由 TransitionGroup 管理,每個內部的 transition 元件都可以設計自己的動畫。
以下是官方範例,點擊刪除按鈕時,列表中的某個項目會被刪除,項目對應到的 in 屬性會被自動改為 false,觸發離場動畫。
function TodoList() {
const [items, setItems] = useState([
{ id: uuid(), text: 'Buy eggs' },
{ id: uuid(), text: 'Pay bills' },
{ id: uuid(), text: 'Invite friends over' },
{ id: uuid(), text: 'Fix the TV' },
]);
return (
<Container style={{ marginTop: '2rem' }}>
<ListGroup style={{ marginBottom: '1rem' }}>
<TransitionGroup className="todo-list">
{items.map(({ id, text }) => (
<CSSTransition
key={id}
timeout={500}
classNames="item"
>
<ListGroup.Item>
<Button
className="remove-btn"
variant="danger"
size="sm"
onClick={() =>
setItems(items =>
items.filter(item => item.id !== id)
)
}
>
×
</Button>
{text}
</ListGroup.Item>
</CSSTransition>
))}
</TransitionGroup>
</ListGroup>
<Button
onClick={() => {
const text = prompt('Enter some text');
if (text) {
setItems(items => [
...items,
{ id: uuid(), text },
]);
}
}}
>
Add Item
</Button>
</Container>
);
}
最後,React Transition Group 也可以搭配 react router 一起使用,可參考以下連結: