Ví dụ React-Transition-Group CSSTransition (NodeJS)

Xem thêm các chuyên mục:

1- Mục tiêu của bài học

Thư viện react-transition-group cung cấp cho bạn các thành phần để bạn tạo ra các hiệu ứng hoạt hình trong ứng dụng React. Bài viết dưới đây giới thiệu chi tiết về thư viện này, các thành phần mà nó cung cấp, các API,..
Trong bài học này tôi sẽ hướng dẫn bạn tạo ứng dụng React trên môi trường NodeJS, sử dụng thành phần <CSSTransition> được cung cấp bởi thư viện react-transition-group.
Chú ý rằng: Thành phần <CSSTransition> là một trường hợp riêng giúp làm việc với CSS Transition dễ dàng hơn, trong trường hợp tổng quát bạn nên làm việc với thành phần <Transition>.

2- Tạo project và cài đặt thư viện

Tạo một dự án React với tên csstransition-app bằng cách thực hiện các lệnh dưới đây:
# Install 'create-react-app' tool (If it has never been installed)

npm install -g create-react-app

# Create project with 'create-react-app' tool:

create-react-app csstransition-app
Cài đặt thư viện react-transition-group:
# CD to your project

cd csstransition-app

# Install 'react-transition-group':

npm install react-transition-group --save
 
Chạy ứng dụng của bạn:
# Run app:

npm start

3- Ví dụ CSSTransition đơn giản

OK, dưới đây là hình ảnh xem trước của ví dụ này.
Khi giá trị của props: 'in' chuyển từ false thành true, <CSSTransition> sẽ chuyển sang trạng thái 'entering', và giữ trong trạng thái này 'timeout' mili giây, trước khi chuyển sang trạng thái 'entered'. Trong quá trình đó các lớp CSS sẽ được áp dụng cho thành phần con của <CSSTransition>, giống như hình minh họa dưới đây:
Khi giá trị của props: 'in' chuyển từ true thành false, <CSSTransition> sẽ chuyển sang trạng thái 'exiting', và giữ trong trạng thái này 'timeout' mili giây, trước khi chuyển sang trạng thái 'exited'. Trong quá trình đó các lớp CSS sẽ được áp dụng cho thành phần con của <CSSTransition>, giống như hình minh họa dưới đây:
OK, Trở lại với project trên. Xóa hết nội dung của các tập tin App.js & App.css:
App.css
.example-enter {
  opacity: 0.2;
  transition: opacity 300ms ease-in;
  background:  #f9e79f;
}

.example-enter .example-enter-active {
  opacity: 1;
  background:  #eafaf1 ;
}

.example-enter-done {
  opacity: 1;
  background:  #eafaf1 ;
}

.example-exit {
  opacity: 1;
  transition: opacity 900ms ease-in;
  background:  #fdebd0 ;
}

.example-exit .example-exit-active {
  opacity: 0.5;
  background:  white ;
}

.example-exit-done {
  opacity: 1;
  background:  white;
}


.my-div {
  border: 1px solid blue;
  width: 350px;
  height: 150px;
  padding: 5px;
}

.my-message {
   font-style: italic;
   color: blue;
}

.my-highlight  {
  color: red;
}
 
App.js
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';

import { TransitionGroup, CSSTransition } from "react-transition-group";

class App extends React.Component  {

    render()  {
      return (
          <div>
             <MyDiv></MyDiv>
          </div>
        );
    }
}

class MyDiv extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      stateOfIn: false,
      message : ""
    };
  }

  // Begin Enter: Do anything!
  onEnterHandler()  {
     this.setState({message: 'Begin Enter...'});
  }

  onEnteredHandler ()  {
     this.setState({message: 'OK Entered!'});
  }

  onEnteringHandler() {
     this.setState({message: 'Entering... (Wait timeout!)'});
  }

  // Begin Exit: Do anything!
  onExitHandler() {
     this.setState({message: 'Begin Exit...'});
  }

  onExitingHandler() {
     this.setState({message: 'Exiting... (Wait timeout!)'});
  }

  onExitedHandler() {
     this.setState({message: 'OK Exited!'});
  }

  render()  {

    return (
          <div>
            <CSSTransition
              classNames="example"
              in={this.state.stateOfIn}

              timeout={1500}

              onEnter = {() =>  this.onEnterHandler()}
              onEntering = {() =>  this.onEnteringHandler()}
              onEntered={() =>  this.onEnteredHandler()}

              onExit={() =>  this.onExitHandler()}
              onExiting={() =>  this.onExitingHandler()}
              onExited={() =>  this.onExitedHandler()}
            >
              <div className ="my-div">
                 <b>{"\u2728"} Click the buttons and see the effects:</b>
                 <ul>
                    <li className ="my-highlight">Now 'in' = {String(this.state.stateOfIn)}</li>
                    <li>  false --&gt; true (Enter)</li>
                    <li>  true  --&gt; false (Exit)</li>
                 </ul>
                 <div className="my-message">{this.state.message}</div>
              </div>

            </CSSTransition>
            <h3>&lt;CSSTransition in={'{this.state.stateOfIn}'} &gt;</h3>

            <button onClick={() => {this.setState({ stateOfIn: true });}}>Set stateOfIn = true</button>
            <button onClick={() => {this.setState({ stateOfIn: false });}}>Set stateOfIn = false</button>
          </div>
        );
  }
}

export default App;
Không cần thay đổi nội dung của các tập tin index.js & index.html:
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';

ReactDOM.render(<App />, document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: http://bit.ly/CRA-PWA
serviceWorker.unregister();
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <meta name="theme-color" content="#000000">
    <link rel="manifest" href="%PUBLIC_URL%/manifest.json">
    <title>React CssTransition</title>
  </head>
  <body>
    <noscript>
      You need to enable JavaScript to run this app.
    </noscript>
    <div id="root"></div>
  </body>
</html>

Xem thêm các chuyên mục: