Các loại hook cơ bản trong React(phần 2)

4 min read

Trong phần 2 này, chúng ta sẽ tiếp tục tìm hiểu cách sử dụng những hook sau: useReducer, useMemo

1. useReducer

useReducer là hook cho phép thêm biến “reducer” đến component của bạn, được sử dụng để quản lý trạng thái của component với logic xử lý phức tạp. Nó giúp tái sử dụng logic xử lý trạng thái và giảm cặp giữa các hàm xử lý và trạng thái.

– Cách sử dụng:  const [state, dispatch] = useReducer(reducer, initialArg, init?)

  • hàm reducer chỉ định cách state được cập nhật
  • initialArgr" là giá trị khởi tạo cho state (initial state) được tính toán, cách tính state khởi tạo dựa trên đổi số tiếp theo(init)
  • init hàm khởi tạo sẽ trả về trạng thái ban đầu(initial state). Nếu tham số “int” không được truyền, trạng thái ban đầu((initial state) sẽ được đặt thành initArg. Nếu không, trạng thái ban đầu((initial state) được đặt thành kết quả của lệnh gọi init(initialArg).

– Hook này được sử dụng trong các trường hợp:

1. Khi trạng thái của component phức tạp và có nhiều hành động (actions) để thay đổi state.

ví dụ:

  • Tôi đã gửi actions nhưng việc ghi lại cho tôi giá trị state cũ
  • Tôi đã gửi hành động nhưng màn hình không cập nhật

2. Nếu logic để thay đổi trạng thái của bạn phức tạp và không phải là một sự tăng giảm đơn giản.
3. Khi cần truyền hàm thay đổi trạng thái qua props, useReducer cho phép bạn truyền một hàm thay đổi trạng thái qua props, giúp quản lý trạng thái ở cấp độ cao hơn trong cây component.

4. reducer và initializer những hàm này bị chạy 2 lần

– Mục đích sử dụng:

1. Giúp quản lý trạng thái của component một cách có tổ chức và dễ bảo trì khi trạng thái(state) trở nên phức tạp.
2. Logic để thay đổi state được đưa vào “reducer” giúp component trở nên dễ đọc và tái sử dụng hơn

– Những lưu ý khi sử dụng:

1. Không sử dụng đối với những xử lý state đơn giản
2. Reducer phải trả về một state mới, không thay đổi state hiện tại. Điều này quan trọng để đảm bảo sự không thay đổi của state làm cho quy trình render hiệu quả.
3. Xác định rõ action types: Đặt tên hành động (action) một cách rõ ràng để dễ dàng theo dõi trong reducer và component

Hãy chạy thử đoạn code sau để hiểu cách sử dụng của useReducer

import { useReducer } from 'react';


function reducer(state, action) {
  if (action.type === 'incremented_age') {
    return {
      age: state.age + 1
    };
  }
  throw Error('Unknown action.');
}


export default function Counter() {
  const [state, dispatch] = useReducer(reducer, { age: 42 });


  return (
    <>
      <button onClick={() => {
        dispatch({ type: 'incremented_age' })
      }}>
        Increment age
      </button>
      <p>Hello! You are {state.age}.</p>
    </>
  );
}

2. useMemo

useMemo cho phép bạn lưu trữ kết quả tính toán giữa các lần hiển thị lại, để tránh việc tính toán lại khi các dependencies không thay đổi.

– Cách sử dụng:  const cachedValue = useMemo(calculateValue, dependencies)

  • calculateValue: Hàm tính toán giá trị mà bạn muốn lưu vào cache. Nó phải thuần túy, không có đối số(no arguments) và phải trả về bất kỳ giá trị nào. React sẽ gọi hàm của bạn trong lần hiển thị đầu tiên(initial render). Trong lần hiển thị tiếp theo(next renders), React sẽ trả về cùng một giá trị nếu phần phụ thuộc không thay đổi kể từ lần hiển thị cuối cùng. Nếu không, nó sẽ gọi hàm CalculateValue, trả về kết quả và lưu trữ để có thể sử dụng lại sau này.
  • dependencies: Bao gồm list tất cả các phụ thuộc để tính toán logic trong hàm calculateValue bao gồm props, state, và tất cả các biến and functions được khai báo trực tiếp bên trong component của bạn(component body). Nếu các thành phần phụ thuộc này có sự thay đổi thì useMemo mới được tính toán lại.

– Mục đích sử dụng: 

  • Bỏ qua những tính toán lại
  • Bỏ qua việc hiển thị lại(re-rendering) components
  • Ghi nhớ sự phụ thuộc của Hooks khác
  • Ghi nhớ một chức năng

– Những lưu ý khi sử dụng
+ Trong lần hiển thị đầu tiên(initial render), useMemo trả về kết quả của việc gọi hàm CalculateValue mà không có đối số.
+ Trong các lần hiển thị tiếp theo, nó sẽ trả về một giá trị đã được lưu trữ từ lần hiển thị cuối cùng (nếu các phần phụ thuộc không thay đổi) hoặc gọi lại CalculateValue và trả về kết quả mà CalculateValue đã trả về

+ useMemo là một Hook, vì vậy bạn chỉ có thể gọi nó ở đầu Component của bạn hoặc Hooks riêng của bạn. Bạn không thể gọi nó bên trong vòng lặp(loops) hoặc điều kiện(conditions). Nếu bạn cần điều đó, hãy trích xuất một component mới và chuyển trạng thái vào đó.

+ Không cần sử dụng useMemo cho mọi biểu thức, chỉ sử dụng khi có sự cần thiết. Xác định rõ dependencies để useMemo có thể hoạt động chính xác. Hạn chế sử dụng trong các trường hợp đơn giản: Trong một số trường hợp đơn giản, việc sử dụng useMemo có thể làm cho code trở nên phức tạp hơn mà không mang lại lợi ích nhiều.

Hãy chạy thử đoạn code sau để hiểu nó:

import { useMemo } from 'react';
import List from './List.js';
import { filterTodos } from './utils.js'


export default function TodoList({ todos, theme, tab }) {
  const visibleTodos = useMemo(
    () => filterTodos(todos, tab),
    [todos, tab]
  );
  return (
    <div className={theme}>
      <p><b>Note: <code>List</code> is artificially slowed down!</b></p>
      <List items={visibleTodos} />
    </div>
  );
}

Xem tiếp về cách sử dụng các hook khác ở bài Các loại hook cơ bản trong React(phần 3)

Nguồn dịch: (https://react.dev/reference/react/useMemo)

Avatar photo

Clean Code: Nguyên tắc viết hàm trong lập trình…

Trong quá trình phát triển phần mềm, việc viết mã nguồn dễ đọc, dễ hiểu là yếu tố then chốt để đảm bảo code...
Avatar photo Dat Tran Thanh
3 min read

Clean Code: Nguyên tắc comment trong lập trình

Trong lập trình, code không chỉ là một tập hợp các câu lệnh để máy tính thực thi, mà còn là một hình thức...
Avatar photo Dat Tran Thanh
3 min read

Clean Code: Nguyên tắc xử lý lỗi (Error Handling)

Trong quá trình phát triển phần mềm, việc xử lý lỗi không chỉ là một phần quan trọng mà còn ảnh hưởng trực tiếp...
Avatar photo Dat Tran Thanh
4 min read

One Reply to “Các loại hook cơ bản trong React(phần 2)”

Leave a Reply

Your email address will not be published. Required fields are marked *