-->
ads here

Introduction React hooks

advertise here
Hôm nay mình xin giới thiệu đến các bạn một tính năng mới xuất hiện ở React 16.8 - React Hooks. Vậy chúng ta cùng xem React hooks là gì, vì sao nó được ra đời và cách sử dụng cơ bản của React hook nhé.
Bài viết hôm nay sẽ gồm các mục chính như sau
  1. Giới thiệu React Hooks
  2. State hook là gì? Cách dùng state hook
  3. Effect hook và cách sử dụng.
  4. Create custom hook.
Let's begin!
Image result for react hooks

1. Giới thiệu React hooks

Hook là một tính năng được thêm vào React từ version 16.8, nó cho phép chúng ta sử dụng state cũng như các tính năng khác của React mà không phải viết dưới component dưới dạng class.
Về bản chất, Hook là một tập các function cho phép ta tác động vào các Component instance, để từ đó có thể tạo ra các Stateful component hoặc access các component lifecycle mà không cần đến class instance.
Lấy 1 ví dụ để dễ hiểu hơn. Giả sử chúng ta cần hiện thực 1 counter với tính năng, click vào nút sẽ tăng số hiển thị trên nút đó lên 1 đơn vị. Với các version trước 16.8 ta làm như sau:


 import React from 'react'  
 class Counter extends React.Component {  
      state = {  
       count: 0,  
  };  
  increase(){  
       this.setState({  
        count: this.state.count+1  
   })  
  }  
  render() {  
   const { count } = this.state;  
   return (  
    <div>  
     <p>You clicked {count} times</p>  
     <button onClick={() => this.increase()}>  
      Click me  
     </button>  
    </div>  
   );  
  }  
 }  

Khi áp dụng React hook ta có thể viết lại như sau

 import React, { useState } from 'react'  
 const Counter = () => {  
  const [count, setCount] = useState(0);  
  return (  
   <div>  
    <p>You clicked {count} times</p>  
    <button onClick={() => setCount(count + 1)}>  
     Click me  
    </button>  
   </div>  
  );   
 }  

Chúng ta có thể thấy, nếu như trước đây, nếu muốn access vào state của Component thì bắt buộc phải viết dưới dạng class (Stateful Component), chứ không thể viết dạng Functional/Stateless  Component. Nhờ có React Hook, ta bây giờ có thể gọi state trong Stateless Component. Và đồng thời khiến code của chúng ta ngắn gọn hơn rất nhiều.

2. State hook là gì? Cách sử dụng state hook

Trước tiên để hiểu State hook là gì, chúng ta sẽ xét ví dụ về 1 color selector như sau: Chúng ta có một selector chứa các option là các màu sắc, khi click vào chọn thì sẽ hiển thị tên của màu đó.

Chúng ta sẽ hiện thực bằng cách sử dụng class như sau:

 import React from 'react'  
 const colors = [  
      'red', 'blue', 'green',  
 ]  
 class ColorsChanger extends React.Component {  
      state= {  
       color: colors[0],  
  }  
  render() {  
       const {color} = this.state;  
       return (  
        <React.Fragment>  
     <select value={color} onChange={e => this.setState({color: e.target.value})}>  
      {colors.map((color) => {  
       return (  
        <option key={color} value={color}>{color}</option>  
       )  
      })}  
     </select>  
     <h3>Color: {color}</h3>  
   </React.Fragment>  
   )  
  }  
 }  

State hook là gì?

Như định nghĩa ở trên, hook là những function cho phép sử dụng các tính năng của React ở vào trong Component. Và ở đây state hook cho phép ta thêm React state vào trong functional component. Như ví dụ ở trên, nếu ta viết ColorsChanger dưới dạng functional Component thì không thể nào sử dụng state được. Nếu muốn dùng state và thay đổi state của Component, trước đây ta buộc phải convert code lại theo dạng class như ví dụ. Nhờ có state hook, ta không cần viết lại Component dạng class mà vẫn có thể sử dụng state trong functional component

 import React, { useState } from 'react'  
 const colors = [  
      'red', 'blue', 'green',  
 ]  
 const ColorsChanger = () => {  
  const [color, setColor] = useState(colors[0]);  
  return (  
   <React.Fragment>  
    <select value={color} onChange={e => setColor(e.target.value)}>  
         {colors.map((color) => {  
          return (  
           <option key={color} value={color}>{color}</option>  
      )  
     })}  
    </select>  
    <h3>Color: {color}</h3>  
  </React.Fragment>  
 )  
 } 

Cách sử dụng state hook

Để sử dụng state hook, trước tiên ta cần import function useState từ React vào bên trong Component. Hàm useState sẽ cho phép ta thêm state và cách thay đổi state vào bên trong Component đó.
const [color, setColor] = useState(colors[0])
Như ta thấy, color sẽ là state và setColor là hàm để update state đó, nó sẽ tương ứng với this.state.color và this.setState({color: <value>}) trong class Component. Và hàm useState nhận tham số là giá trị mặc định của state (giá trị này có thể là bất kì type nào).
Có cách viết khác tường minh hơn của useState như sau:
const state = useState(colors[0]);
const color = state[0];
const setColor = state[1];
Chúng ta build lại và thấy ứng dụng chạy đúng như cách class Component ban đầu chạy. Như vậy là ta đã có thể sử dụng state bên trong functional Component mà không cần viết lại dưới dạng class.
Và nếu Component cần nhiều hơn 1 state, chúng ta hoàn toàn có thể dùng nhiều hơn 1 state hook trong 1 component
const [color, setColor] = useState(colors[0]);
const [name, setName] = useState("Julian Dong"); 
Tiếp theo chúng ta sẽ tìm hiểu đến Effect hook, cho phép ta thực hiện các side effect bên trong component.

3. Effect hook và cách sử dụng

Ta tiếp tục mở rộng ví dụ ở trên như sau: Với mỗi màu sắc được chọn, tên màu sắc sẽ được hiển thị ở h3 tag đồng thời nó có màu ứng với màu đã chọn ở select tag.

Effect hook cho phép ta thực thi các side effect bên trong functional component.
Side effect bao gồm fetch data, setup subscription hay thay đổi cấu trúc DOM.
Ta sử dụng effect hook khi muốn access vào các stage của lifecycle của React. Để sử dụng effect hook ta thêm hàm useEffect vào trong component như sau
 import React, { useState, useEffect } from 'react'  
 const colors = [  
      'red', 'blue', 'green',  
 ]  
 const ColorsChanger = () => {  
      const [color, setColor] = useState(colors[0]);  
  useEffect(  
       () => {  
        document.getElementById('colorText').style.color = color  
   }  
  )  
      return (  
       <React.Fragment>  
    <select value={color} onChange={e => setColor(e.target.value)}>  
         {colors.map((color) => {  
          return (  
           <option key={color} value={color}>{color}</option>  
      )  
     })}  
    </select>  
    <h3 id="colorText">Color: {color}</h3>  
   </React.Fragment>  
  )  
 }  

Khi đó, mỗi khi ta thay đổi màu được chọn, thì màu của h3 sẽ thay đổi theo. Ta có thể thấy, mỗi lần render thì useEffect đều sẽ chạy. Ta có thể coi useEffect là sự kết hợp của componentDidMount, componentDidUpdatecomponentWillUnmount
useEffect === componentDidMount + componentDidUpdate + componentWillUnmount
Và tương tự useState, ta cũng có thể sử dụng nhiều useEffect trong 1 Component.
Trước khi qua mục tiếp theo, chúng ta hãy cùng điểm qua một số nguyên tắc khi sử dụng React hook,

  1. Chỉ sử dụng hook ở Top level, tức là không nên dùng bên trong if hay các vòng lặp cũng như các nested function
  2. Chỉ sử dụng hook từ các React function tức là chỉ gọi bên trong functional function hoặc được gọi từ các custom hook, không gọi hook từ các javascript function thông thường.
Tiếp theo chúng ta sẽ tìm hiểu cách để tạo ra các custom hook của riêng ta khi cần thiết.

4. Create custom hook

Trong phần cuối cùng của bài viết này chúng ta sẽ làm một ví dụ về tạo ra riêng 1 hook của cho mình bằng cách kết hợp State hook và Effect hook. Ở ví dụ này chúng ta sẽ hiện thực việc hiển thị vị trí của chuột trên màn hình.
Tiến hành phân tích vấn đề như sau:

  • Ta cần sử dụng State hook để cập nhật toạ độ x và y của mouse khi di chuyển
  • Đối với mỗi lần di chuyển ta cần lấy được toạ độ của chuột và cập nhật nó để hiển thị, khi đó ta cần dùng Effect hook và hàm window.addEventListener() để thực thi side effect.
Ta tiến hành code như sau

 import React, { useState, useEffect } from "react";  
 const useMousePosition = () => {  
  const [x, setX] = useState();  
  const [y, setY] = useState();  
  const update = e => {  
   setX(e.x);  
   setY(e.y);  
  };  
  useEffect(  
   () => {  
    window.addEventListener("mousemove", update);  
    return () => window.removeEventListener("mousemove", update);  
   },  
   [x, y]  
  );  
  return { x, y };  
 };  
 const App = () => {  
  const { x, y } = useMousePosition()  
  return x && y ? <h1>{`x:${x} - y: ${y}`}</h1> : null;  
 };  


  • Đầu tiên ta hiện thực 1 custom hook tên là useMousePosition, sử dụng từ use là để biết đó là 1 hook.
  • Trong hook này, ta sẽ cần cập nhật giá trị của x và y của chuột khi đó ta cần dùng useState cho x và y. Đồng thời viết hàm update nhận vào 1 event và có nhiệm vụ cập nhật giá trị x,y.
  • Khi ta rê chuột thì sự kiên 'mousemove' sẽ được gọi và ta dùng useEffect này để xử lý sử kiện rê chuột bằng cách update giá trị x, y.
  • Cuối cùng hook này sẽ trả về lại giá trị của x,y bằng return {x,y};
  • Sau khi hoàn thành hook, ta sẽ được kết quả như sau 

Vậy là custom hook đã được hoàn thành!

Kết

Qua bài viết này mình hi vọng giúp các bạn hiểu thêm về 1 tính năng mới của React và có thể vận dụng nó trong quá trình làm việc với React. Bên cạnh useState và useEffect, còn có nhiều hook khác để bạn có thể đọc và sử dụng như useReducer, useCallback... Các bạn có thể đọc thêm tại đây

Cảm ơn các bạn đã đọc bài viết của mình, nếu thấy có ích hãy cùng chia sẻ cho mọi người cùng biết. Nếu bạn có bất kì ý kiến đóng góp nào đừng ngần ngại để lại comment bên dưới bài viết này nhé!

Reference


Advertisement
COMMENTS ()