Anh em mình code React chắc không lạ gì cảnh component ngày càng phình to, logic state và side effect đan xen nhau như mớ bòng bong, đặc biệt là khi chuyển từ class component qua. Ngày xưa mình cũng vật lộn với this.state và một rổ lifecycle methods. Từ khi React 16.8 ra đời với Hooks, cuộc đời developer chúng mình như sang một trang mới. Trọng tâm của sự thay đổi đó chính là useState và useEffect – hai "siêu anh hùng" trong bài React Hooks useState useEffect hướng dẫn này – giúp code sạch hơn, logic dễ theo dõi hơn hẳn.
State management has never been easier with useState
Quản lý trạng thái trong React Hooks đã trở nên vô cùng trực quan nhờ useState. Nó loại bỏ hoàn toàn sự phức tạp của từ khóa this và giúp bạn tách bạch các luồng dữ liệu một cách độc lập.
What are React Hooks that are so "divine"?
React Hooks are special functions that allow you to "hook" core React features like state management and lifecycle right inside Functional Components without writing Classes.
Previously, to store data changes on the interface, we were required to use Class Components. This makes the code lengthy, difficult to read, and extremely difficult to reuse logic between components. The introduction of Hooks from React version 16.8 has completely changed the landscape of web development. It helps Functional Components become as powerful and flexible as Classes. If you're taking your first step into this world, a Learning React JS from scratch for beginners roadmap will be a great stepping stone. At Pham Hai, through the process of training many generations of programmers, I always emphasize that deeply understanding the nature of Hooks is the key to writing modern React code.
useState là gì? Nói lời tạm biệt với this.state
useState là một Hook cơ bản trong React cho phép bạn khai báo, đọc và cập nhật trạng thái (state) cục bộ trực tiếp bên trong một Functional Component.
Khi gọi useState, nó sẽ trả về cho bạn một mảng gồm đúng hai phần tử: giá trị state hiện tại và một hàm (setter function) dùng để cập nhật giá trị đó. Cú pháp này tận dụng tính năng destructuring rất thanh lịch của JavaScript. Nếu bạn chưa quen với cách viết này, hãy xem lại ngay các ES6 JavaScript tính năng mới cần biết. Khác với this.state rườm rà gộp chung mọi thứ vào một object lớn, useState cho phép khai báo trực tiếp và độc lập từng biến (ví dụ: một biến cho tên, một biến cho tuổi). Điều này giúp việc theo dõi luồng dữ liệu tường minh hơn rất nhiều.
How to use useState in React: From basics to advanced
Cách sử dụng useState trong React bắt đầu bằng việc import nó từ thư viện 'react', sau đó gọi hook này ở ngay dòng đầu tiên của component với một giá trị khởi tạo tùy ý.
Ví dụ cơ bản nhất là làm một bộ đếm: const [count, setCount] = useState(0);. Mỗi khi user click và bạn gọi hàm setCount(count + 1), React sẽ tự động kích hoạt quá trình Render/Re-render để cập nhật con số mới lên giao diện. Tuy nhiên, có một kỹ thuật nâng cao bạn bắt buộc phải biết: sử dụng Callback function khi cập nhật state. Thay vì viết setCount(count + 1), hãy dùng setCount(prevCount => prevCount + 1). Cách viết này giúp lấy được giá trị state mới nhất một cách an toàn, đặc biệt khi có nhiều thao tác cập nhật diễn ra liên tiếp. Quá trình này đòi hỏi bạn phải nắm vững cách JS xử lý hàm, nên việc ôn luyện Học JavaScript cơ bản cho người mới 2026 là nền tảng không bao giờ thừa.
"Fatal" mistakes when using useState and how to avoid them
The most common mistake is updating the state directly (mutate state) instead of using a setter function, or initializing the state with heavy calculation functions that choke performance.
Khi làm việc với object hoặc mảng trong state, tuyệt đối không được sửa trực tiếp kiểu state.user = 'Hải'. Bạn luôn phải tạo một bản sao mới (clone) rồi mới truyền vào hàm set. Để xử lý mảng hiệu quả và không làm thay đổi mảng gốc, các kỹ thuật JavaScript Array methods map filter reduce chính là vũ khí không thể thiếu. Ngoài ra, để React Hooks tối ưu hiệu suất, nếu giá trị khởi tạo ban đầu đòi hỏi tính toán phức tạp (ví dụ đọc từ localStorage), hãy truyền một function vào useState (được gọi là lazy initialization). Bằng cách này, hàm tính toán sẽ chỉ chạy đúng một lần duy nhất ở lần render đầu tiên.
Handle side effects neatly with useEffect
Bên cạnh state, việc tương tác với thế giới bên ngoài component cũng quan trọng không kém. Xử lý side effect trong React Hooks được quy chuẩn hóa một cách thanh lịch thông qua useEffect.
What is useEffect? Perfect replacement for lifecycle methods
useEffect là một Hook cho phép bạn thực hiện các tác vụ phụ (side effects) trong Functional Component, đóng vai trò thay thế cho các lifecycle methods cũ như componentDidMount, componentDidUpdate, và componentWillUnmount.
Side Effects là những thao tác tác động ra khỏi phạm vi của một component, ví dụ như gọi API lấy dữ liệu, thao tác trực tiếp với DOM, hoặc thiết lập các bộ đếm thời gian (timers). Việc gom chung các logic này vào useEffect giúp code liên quan đến một tính năng không bị chia cắt rải rác. Nếu bạn đang xây dựng các hiệu ứng phức tạp cần can thiệp trực tiếp vào giao diện, kiến thức về DOM JavaScript thao tác phần tử HTML sẽ kết hợp hoàn hảo với Hook này để tạo ra trải nghiệm người dùng mượt mà.
How to use useEffect in React: Dependency arrays are no longer an obsession
Cách sử dụng useEffect trong React chuẩn xác nhất là truyền vào nó một hàm callback chứa logic side effect và một Dependency array để kiểm soát chặt chẽ thời điểm effect đó được phép chạy lại.
The Dependency array in useEffect is what decides the "life and death" of the app.
- Nếu bạn để mảng rỗng
[], effect chạy đúng 1 lần duy nhất khi component xuất hiện (mount). - If you forget to pass the array, the effect will rerun after each render – this is the number 1 cause of infinite loop errors that crash the browser.
- If there are variables in the array (Dependencies), the effect only runs again when one of those variables changes value.
Theo kinh nghiệm 10 năm của mình, việc quản lý mảng dependency sai cách là lỗi phổ biến nhất của các bạn mới. Always check carefully to see which variables are used inside the effect and must be included in this array.
Real-life example: Use useEffect to call APIs like a pro
Để thực hiện Data fetching một cách chuẩn mực, bạn đặt logic gọi API bên trong useEffect với dependency array rỗng, đảm bảo dữ liệu chỉ được tải một lần khi component vừa render xong.
Đây là một React Hooks ví dụ thực tế cực kỳ kinh điển. Kết hợp React Hooks với API luôn yêu cầu xử lý bất đồng bộ. Vì bản thân hàm callback của useEffect không được phép là một async function, bạn cần khai báo một hàm async nhỏ bên trong nó rồi mới gọi thực thi. Để hiểu sâu hơn về cơ chế chờ đợi phản hồi này, bạn nên nắm vững Async Await Promise JavaScript dễ hiểu. Trong thực tế, chúng ta thường dùng Fetch API gọi REST API bằng JavaScript ngay bên trong hàm async này để lấy dữ liệu từ server và lưu vào state. Mặc dù tính đến năm 2026, React 19 đã bổ sung thêm hook use() mới cho Server Components, nhưng ở môi trường Client, useEffect vẫn là tiêu chuẩn vàng,.
Don't forget the cleanup function in useEffect to avoid memory leaks!
Cleanup function là một hàm được return từ bên trong useEffect, có nhiệm vụ dọn dẹp các tài nguyên như event listener hay timer trước khi component bị hủy (unmount) hoặc trước khi effect chạy lại lần tiếp theo.
Nếu bạn đăng ký một sự kiện lắng nghe cuộn chuột (window.addEventListener('scroll', ...)) mà quên Clean up, mỗi lần component re-render nó sẽ tạo thêm một listener mới. Tích tụ dần, ứng dụng của bạn sẽ bị rò rỉ bộ nhớ (memory leak) và trở nên giật lag. Việc trả về Cleanup function useEffect là quy tắc bắt buộc để giữ cho ứng dụng khỏe mạnh. Hãy coi nó như việc bạn dọn dẹp sạch sẽ phòng trọ trước khi trả phòng vậy.
Compare Functional Component (with Hooks) and Class Component
The shift from Class to Functional Component is not just a change in syntax, but a big step forward in software design thinking in the React ecosystem.
Code before and after Hooks: One heaven and one earth
So sánh functional component và class component React cho thấy Hooks giúp giảm thiểu đáng kể lượng boilerplate code, loại bỏ hoàn toàn từ khóa this rắc rối và gom nhóm logic theo chức năng.
Here's a quick comparison table to show you the differences:
| Criteria | Class Component | Functional Component (with Hooks) |
|---|---|---|
| Cú pháp & Độ dài | Long, lots of boilerplate code | Short, concise, easy to read |
| Quản lý State | Dùng this.state và this.setState |
Dùng useState linh hoạt |
| Side Effects | Distributed across many Lifecycle methods | Gom chung gọn gàng vào useEffect |
Trong Class, logic gọi API và dọn dẹp thường bị xé lẻ ở componentDidMount và componentWillUnmount. Với Hooks, mọi thứ nằm gọn trong một khối useEffect duy nhất. Code ngắn hơn đồng nghĩa với việc ít bug hơn và bảo trì nhàn hơn rất nhiều.
Tại sao Functional Component lại là xu hướng?
Functional component kết hợp với Hooks trở thành tiêu chuẩn công nghiệp vì chúng nhẹ hơn, dễ viết test hơn và đặc biệt là khả năng chia sẻ logic cực kỳ mạnh mẽ.
Ngoài việc nhận Props đầu vào và trả về giao diện UI, Functional Component giờ đây có thể gánh vác mọi trọng trách phức tạp nhất. Toàn bộ hệ sinh thái React hiện tại, từ tài liệu chính thức đến các thư viện UI nổi tiếng, đều viết dựa trên Hooks. Các bản cập nhật mới nhất của React 19 (năm 2026) với React Compiler tự động tối ưu hóa hiệu suất càng củng cố vị thế độc tôn của Functional Component, giúp chúng chạy mượt mà mà không cần lập trình viên phải can thiệp tối ưu thủ công quá nhiều.
Nâng tầm kỹ năng: Viết Custom Hooks cho riêng mình
Khi đã thành thạo useState và useEffect, bước tiếp theo để trở thành một Senior Developer là biết cách tự tạo ra các Hooks của riêng mình.
Custom Hook là gì và tại sao bạn nên quan tâm?
Custom Hooks trong React thực chất chỉ là các hàm JavaScript thông thường có tên bắt đầu bằng chữ "use" và có thể gọi các Hooks có sẵn khác ở bên trong nó.
Nó giúp bạn trích xuất các logic xử lý phức tạp ra khỏi giao diện UI để tái sử dụng ở hàng chục component khác nhau. Ví dụ, logic theo dõi trạng thái online/offline của người dùng có thể được gói gọn vào một hook tên là useOnlineStatus. Việc tổ chức code module hóa như thế này mang tư duy rất giống với cách chúng ta chia nhỏ file bằng JavaScript Module import export hướng dẫn, góp phần giúp dự án scale (mở rộng) lên dễ dàng mà không bị rối.
Build a simple Custom Hook to reuse logic
Để tạo Custom Hook, bạn định nghĩa một function mới, mang các useState và useEffect có chung mục đích vào đó, rồi return về những dữ liệu mà component bên ngoài cần dùng.
Giả sử bạn cần fetch data ở 10 màn hình khác nhau. Thay vì lặp đi lặp lại đoạn code useEffect dài ngoằng, hãy viết một Custom Hook tên là useFetch(url). Hook này sẽ tự động quản lý các state như data, isLoading, error và chỉ trả về kết quả cuối cùng cho component. Đây chính là đỉnh cao của việc áp dụng nguyên tắc DRY (Don't Repeat Yourself) và viết code sạch trong React.
Tóm lại, thông qua bài React Hooks useState useEffect hướng dẫn này, hy vọng bạn đã thấy hai hook này không chỉ là công cụ mới mà là một cuộc cách mạng trong tư duy viết code. Nắm vững chúng giúp bạn quản lý trạng thái và side effect một cách tường minh, giúp code dễ đọc và dễ bảo trì. Khi đã vững nền tảng, bạn có thể tự tin khám phá Các Hook khác trong React như useContext (tránh truyền props nhiều tầng), useReducer (quản lý state phức tạp), useMemo, useCallback, hoặc useRef để giải quyết các bài toán khó nhằn hơn. Hãy áp dụng những kiến thức này vào dự án thực tế ngay hôm nay để tự mình cảm nhận sự thanh lịch của code!
Bạn đã có kinh nghiệm "đau thương" hay khoảnh khắc "ngộ đạo" nào với useState và useEffect chưa? Hãy chia sẻ ở phần bình luận bên dưới nhé, tại Phạm Hải, chúng mình luôn rất muốn nghe câu chuyện thực tế từ bạn!
Lưu ý: Thông tin trong bài viết này chỉ mang tính chất tham khảo. Để có lời khuyên tốt nhất, vui lòng liên hệ trực tiếp với chúng tôi để được tư vấn cụ thể dựa trên nhu cầu thực tế của bạn.