React hook

React hook là tính năng mới tuyệt vời trong React 16.8. Nó sẽ là tính năng mà chúng ta sẽ sử dụng hàng ngày để phát triển các dự án React.

Nếu bạn muốn sử dụng state hoặc các phương thức lifecycle, bạn sẽ phải chuyển sang sử dụng React.Component và các class. Hook cho phép chúng ta sử dụng trong functional component.

Hook là gì?

React hook là cách để thêm các tính năng của React.Component vào các functional component. Các tính năng như sau:

  • State
  • Lifecycle

Hook cho phép chúng ta sử dụng các tính năng của React mà không cần sử dụng class

Mặc dù vậy, các class sẽ không bị xoá hoặc không được khuyến khích. Chúng ta đang được cung cấp thêm nhiều cách hơn để code

State của hook

Giả sử chúng ta có một component như sau:

State trong component

import React, { Component } from 'react';

class JustAnotherCounter extends Component {
  state = {
    count: 0
  };

  setCount = () => {
    this.setState({ count: this.state.count + 1 });
  };

  render() {
    return (
      <div>
        <h1>{this.state.count}</h1>

        <button onClick={this.setCount}>Count Up To The Moon</button>
      </div>
    );
  }
}

Nhưng với React hook, chúng ta có thể viết ngắn gọn class bên trong functional component

State với functional component và useState

import React, { useState } from 'react';

function JustAnotherCounter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <h1>{count}</h1>
      <button onClick={() => setCount(count + 1)}>Count Up To The Moon</button>
    </div>
  );
}

Kết quả

Cú pháp useState() là gì?

Bạn có thể sẽ không quen với kiểu sử dụng cú pháp useState(). Cái này sử dụng destructuring assignment cho các mảng. Điều này tương tự như cách chúng ta lấy các prop ra khỏi một object bằng object destructuring

Chúng ta hãy cùng so sánh object destructuring vs array destructuring để thấy rằng tại sao sử dụng mảng lại hữu ích.

Object destructuring đòi hỏi phải viết nhiều hơn để lấy một biến và đổi tên nó

Object Destructuring

// object destructuring. viết nhiều hơn
const users = { admin: 'chris', user: 'nick' };

// lấy admin và user nhưng đổi tên thành SuperAdmin và SuperUser
const { admin: SuperAdmin, user: SuperUser } = users;

Đoạn code bên dưới cùng hơi khó đọc, sử dụng array destructuring, chúng ta chỉ cần đặt tên biến và lấy giá trị tương ứng trong mảng. Biến đầu tiên là phần tử đầu tiên trong mảng.

Array Destructuring

// array destructuring
const users = ['chris', 'nick'];

// lấy gía trị và đổi tên
const [SuperAdmin, SuperUser] = users;

useState là gì?

useState cung cấp 2 biến và chúng ta có thể đặt tên bất kỳ cho 2 biến, chỉ biết rằng:

  • Biến đầu tiên là giá trị, giống như this.state
  • Biến thứ 2 là hàm để cập nhập giá trị, giống như this.setState

Tham số truyền vào cho useState là giá trị khởi tạo. Trong ví dụ trên thì giá trị đếm được bắt đầu từ 0

Sử dụng nhiều State trong Hook

Chúng ta có thể sử dụng useState() nhiều lần trong cùng một hàm

import React, { useState } from 'react';

function AllTheThings() {
  const [count, setCount] = useState(0);
  const [products, setProducts] = useState([{ name: 'Surfboard', price: 100 }]);
  const [coupon, setCoupon] = useState(null);

  return <div>{/_ thêm code vào đây _/}</div>;
}

Effect React Hook

State Hook cho phép chúng ta sử dụng state trong các component functional của React.  Điều này giúp chúng ta tiến thêm một bước gần hơn sử dụng functional component thay cho class component.

Các Effect là tương tự như componentDidMount, componentDidUpdatecomponentWillUnmount

Sau đây là một số đặc điểm của Effect Hook

  • Lấy dữ liệu
  • Cập nhập DOM thủ công (document title)
  • Thiết lập một subcription

Effect sẽ chạy sau tất cả các render bao gồm cả render đầu tiên

Hãy so sánh một class với một functional component

import React, { Component } from 'react';

class DoSomethingCrazy extends Component {
  componentDidMount() {
    console.log('i have arrived at the party!');
    document.title = 'preesent';
  }

  render() {
    return <div>stuff goes here</div>;
  }
}

Khi sử dụng Effect Hook, chúng ta dùng useEffect()

function DoSomethingCrazy() {
  useEffect(() => {
    console.log('i have arrived at the party!');
    document.title = 'preesent';
  });

  return <div>stuff goes here</div>;
}

Kết quả

stuff goes here

useEffect() là hiệu quả không? Giống hệt như componentDidMount và componentDidUpdate

Chỉ chạy Effect Hook khi có thay đổi

Do useEffect() chạy mỗi khi component render, vậy làm thế nào chúng ta chỉ chạy nó một lần khi mount? Effect Hook  nhận tham số thứ 2, một mảng, nó sẽ kiểm tra mảng và chỉ chạy một lần một trong những giá trị trong đó thay đổi.

componentDidMount: Chạy một lần

// chỉ chạy khi mount, truyền vào mảng rỗng
useEffect(() => {
  // only runs once
}, []);

componentDidUpdate: Chạy khi có thay đổi

// Chỉ chạy khi count thay đổi
useEffect(
  () => {
    // Chạy khi count thay đổi
  },
  [count]
);

Nếu bạn muốn chạy một vài thứ trước khi unmount, chúng ta chỉ cần trả về một hàm từ useEffect().

useEffect(() => {
  UsersAPI.subscribeToUserLikes();

  // unsubscribe
  return () => {
    UsersAPI.unsubscribeFromUserLikes();
  };
});

Sử dụng State và Effect cùng nhau

Sẽ không vó vấn đề gì khi sử dụng chúng cùng nhau. Chúng có thể cùng nhau tạo các functional component mà hoạt động giống như class component

Hãy cùng xem ví dụ trong thực tế sau đây: Chúng ta cần lấy danh sách người dùng từ Github sử dụng api với useEffect() và đồng thời sử dụng useState().  Đầu tiên chúng ta sử dụng useState()

import React, { useState } from 'react';

function GitHubUsers() {
  const [users, setUsers] = useState([]);
}

Chúng ta khởi tạo users là một mảng rỗng bằng cách khai báo useState([]). Tiếp theo chúng ta sẽ đưa vào trong Hook useEfffect() và sử dụng fetch để lấy dữ liệu từ Github API.

import React, { useState } from 'react';

function GitHubUsers() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('https://api.github.com/users')
      .then(response => response.json())
      .then(data => {
        setUsers(data); // gán dữ liệu cho users
      });
  }, []); //mảng rổng vì chúng ta chỉ chạy một lần
}

Chú ý rằng tham số thứ 2 của useEffect() truyền vào một mảng rỗng bởi vì chúng ta chỉ muốn chạy một lần duy nhất. Cuối cùng hiển thị kết quả như sau

import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';

function GitHubUsers() {

  return (
    <div className="section">
      {users.map(user => (
        <div key={user.id} className="card">
          <h5>{user.login}</h5>
        </div>
      ))}
    </div>
  );
}

Kết quả

 

You May Also Like

About the Author: Nguyen Dinh Thuc

Leave a Reply

Your email address will not be published.