iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
Modern Web

用30天更加認識 React.js 這個好朋友系列 第 21

Day21-React 簡易動畫篇-下篇

這篇要繼續介紹剩下的兩個元件。

SwitchTransition 元件

主要是用來渲染兩個狀態間做切換的過渡動畫,假如想要讓新元素加入和舊元素移除同時發生時出現動畫,官方網站比較建議使用 TransitionGroup 元件。

SwitchTransition 元件有 props 屬性 mode,當值為:

  • in-out:等待新元素先加入,再等待舊元素移除
  • out-in:等待舊元素先移除,再加入新元素

在使用 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 時都會出現不同的色塊:

程式碼範例

TransitionGroup 元件

用來管理多個 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)
                    )
                  }
                >
                  &times;
                </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

最後,React Transition Group 也可以搭配 react router 一起使用,可參考以下連結:

範例


上一篇
Day20-React 簡易動畫篇-上篇
下一篇
Day22-React Life Cycle 篇-上篇(介紹生命週期圖 & Mounting)
系列文
用30天更加認識 React.js 這個好朋友32

尚未有邦友留言

立即登入留言