Nội dung bài viết
React Hooks là một tính năng quan trọng trong React, được giới thiệu từ phiên bản 16.8, cho phép sử dụng state và các tính năng khác của React trong functional components mà không cần viết class components. Bài viết này sẽ tập trung vào React Hooks, giải thích chi tiết về cách sử dụng và lợi ích của chúng.
React Hooks giúp quản lý state, side effects và lifecycle của component một cách dễ dàng và gọn gàng hơn so với class components.
Tại sao nên sử dụng React Hooks?
Sử dụng React Hooks mang lại nhiều lợi ích, bao gồm:
- Quản lý state và lifecycle dễ dàng hơn: Trước đây, việc quản lý state và lifecycle chỉ có thể thực hiện trong class components. React Hooks cho phép functional components làm điều tương tự, giúp code gọn gàng và dễ hiểu hơn.
// Class component
import React, { Component } from 'react';
class ExampleComponent extends Component {
constructor(props) {
super(props);
this.state = { count: 0 };
}
componentDidMount() {
console.log('Component did mount');
}
// ... other lifecycle methods
incrementCount = () => {
this.setState({ count: this.state.count + 1 });
}
render() {
return (
Count: {this.state.count}
);
}
}
// Functional component với Hooks
import React, { useState, useEffect } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Component did mount');
return () => {
console.log('Component will unmount');
};
}, []);
const incrementCount = () => {
setCount(count + 1);
}
return (
Count: {count}
);
}
export default ExampleComponent;
Giảm độ phức tạp của class components: Class components có thể trở nên phức tạp khi xử lý nhiều state và lifecycle. React Hooks giúp giảm thiểu độ phức tạp này bằng cách chia nhỏ logic thành các đơn vị nhỏ hơn, dễ quản lý hơn.
Cải thiện hiệu suất: React Hooks cung cấp các công cụ như
useMemo
vàuseCallback
để tối ưu hóa hiệu suất bằng cách tránh re-render không cần thiết.Tái sử dụng logic: React Hooks cho phép tạo custom hooks để tái sử dụng logic giữa các components, giảm thiểu code trùng lặp và tăng tính linh hoạt.
Các React Hooks thường dùng
React cung cấp nhiều hooks built-in, bao gồm:
useState()
useState()
dùng để quản lý state trong functional components. Nó trả về một cặp giá trị: biến state hiện tại và một hàm để cập nhật state.
import React, { useState } from 'react';
function ExampleComponent() {
const [count, setCount] = useState(0);
const incrementCount = () => {
setCount(count + 1);
};
return (
Count: {count}
);
}
Lưu ý khi sử dụng useState()
:
- Luôn khởi tạo giá trị ban đầu cho state.
- State được reset về giá trị ban đầu sau mỗi lần refresh trang.
- Component re-render khi state thay đổi.
- Sử dụng hàm updater function để cập nhật state, tránh thay đổi trực tiếp.
Khi nào nên sử dụng useState()
:
- Quản lý trạng thái UI (ví dụ: giá trị input, trạng thái hiển thị/ẩn).
- Lưu trữ dữ liệu tạm thời.
- Xử lý trạng thái form.
useEffect()
useEffect()
dùng để thực hiện side effects trong functional components, ví dụ như gọi API, thao tác DOM, đăng ký/hủy đăng ký event listeners.
import React, { useState, useEffect } from "react";
import axios from "axios";
function ExampleComponent() {
const [data, setData] = useState({});
const getDataFromAPI = async () => {
const response = await axios.get(
"https://jsonplaceholder.typicode.com/todos/1"
);
setData(response.data);
};
useEffect(() => {
getDataFromAPI();
}, []);
return {data.title};
}
export default ExampleComponent;
Dependencies trong useEffect()
:
- Không có dependencies:
useEffect
chạy sau mỗi lần render. - Mảng rỗng
[]
:useEffect
chạy một lần sau khi component mount (tương tựcomponentDidMount
). - Mảng chứa props/state:
useEffect
chạy khi giá trị của dependencies thay đổi (tương tựcomponentDidUpdate
).
Cleanup function trong useEffect()
:
Dùng để dọn dẹp side effects, ví dụ như hủy đăng ký event listeners khi component unmount.
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
Khi nào nên sử dụng useEffect()
:
- Gọi API.
- Thao tác DOM.
- Đăng ký/hủy đăng ký event listeners.
- Thực hiện các tác vụ sau khi render.
useLayoutEffect()
useLayoutEffect()
tương tự useEffect()
, nhưng chạy đồng bộ ngay sau khi DOM updates, trước khi browser vẽ lại giao diện. Thường dùng cho các tác vụ liên quan đến layout hoặc đồ họa.
import React, { useLayoutEffect, useState } from 'react';
function DrawCanvas() {
const [ctx, setCtx] = useState(null);
useLayoutEffect(() => {
const canvas = document.getElementById('myCanvas');
const context = canvas.getContext('2d');
context.fillStyle = 'red';
context.fillRect(0, 0, 100, 100);
setCtx(context);
}, []);
// ...
}
export default DrawCanvas;
So sánh useLayoutEffect()
và useEffect()
:
useEffect()
chạy bất đồng bộ, sau khi render.useLayoutEffect()
chạy đồng bộ, trước khi browser vẽ lại giao diện.
Khi nào nên sử dụng useLayoutEffect()
:
- Thao tác DOM liên quan đến layout.
- Cần đảm bảo tác vụ hoàn thành trước khi giao diện được cập nhật.
useMemo()
useMemo()
dùng để lưu trữ kết quả của một phép tính, tránh tính toán lại nếu dependencies không thay đổi.
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
Khi nào nên sử dụng useMemo()
:
- Tính toán phức tạp, tốn kém.
- Tối ưu hóa kết quả trung gian.
useCallback()
useCallback()
dùng để lưu trữ một hàm callback, tránh tạo lại hàm nếu dependencies không thay đổi. Hữu ích khi truyền callback làm props cho component con.
const memoizedCallback = useCallback(() => {
// ...
}, [dependencies]);
Khi nào nên sử dụng useCallback()
:
- Tránh re-render không cần thiết ở component con.
- Sử dụng trong mảng dependencies của
useEffect()
.
useRef()
useRef()
tạo một mutable object, thường dùng để truy cập DOM elements hoặc lưu trữ giá trị giữa các lần render mà không gây re-render.
const inputRef = useRef(null);
// ...
Khi nào nên sử dụng useRef()
:
- Truy cập và thao tác DOM elements.
- Lưu trữ giá trị giữa các lần render mà không gây re-render.
useContext()
useContext()
dùng để truy cập giá trị của một React Context.
const value = useContext(MyContext);
Khi nào nên sử dụng useContext()
:
- Chia sẻ dữ liệu global.
- Truyền dữ liệu giữa các components không liên quan trực tiếp.
useReducer()
useReducer()
là một alternative cho useState()
, dùng cho quản lý state phức tạp.
const [state, dispatch] = useReducer(reducer, initialState);
Khi nào nên sử dụng useReducer()
:
- Quản lý state phức tạp.
- Tránh state drift.
- Tái sử dụng logic cập nhật state.
Custom Hooks
Custom Hooks là các hàm bắt đầu bằng “use” và có thể gọi các hooks khác. Dùng để tái sử dụng logic.
function useCustomCounter(initialValue) {
// ...
}
Rule of Hooks
Khi sử dụng Hooks, cần tuân thủ các quy tắc sau:
- Chỉ sử dụng Hooks trong functional components.
- Gọi Hooks ở top level, không gọi trong loops, conditions, nested functions.
- Gọi Hooks theo cùng thứ tự trong mỗi lần render.
Kết luận
React Hooks cung cấp một cách mạnh mẽ và linh hoạt để làm việc với state, side effects và lifecycle trong functional components. Hiểu rõ cách sử dụng và tuân thủ Rule of Hooks sẽ giúp bạn viết code React hiệu quả và dễ bảo trì hơn.
Nội dung được phát triển bởi đội ngũ Meraki Center với mục đích chia sẻ và tăng trải nghiệm khách hàng. Mọi ý kiến đóng góp xin vui lòng liên hệ tổng đài chăm sóc: 1900 0000 hoặc email: [email protected]