ducdev
Frontend / Bài viết

React Hooks — useState, useEffect Và Các Hook Thiết Yếu

Hooks đã thay đổi cách viết React component hoàn toàn từ 2019. Hiểu đúng useState, useEffect, useContext, useRef và useMemo sẽ giúp bạn tránh được phần lớn bug phổ biến.

a
admin
09/08/2025 · 3 phút đọc · 0 lượt xem
Chia sẻ

Trước Hooks, để có state trong component bạn phải dùng class component với this.setState — cú pháp verbose và dễ gây bug. Hooks ra đời năm 2019 và nhanh chóng trở thành cách duy nhất đáng học để viết React.

useState — State Cơ Bản

import { useState } from 'react';

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

    return (
        

Đếm: {count}

); } // State với object function Form() { const [form, setForm] = useState({ name: '', email: '' }); const handleChange = (e) => { setForm(prev => ({ ...prev, [e.target.name]: e.target.value })); }; }

Quan trọng: Luôn dùng functional update (prev =>) khi state mới phụ thuộc state cũ — tránh stale closure bugs.

useEffect — Side Effects

import { useEffect, useState } from 'react';

function PostDetail({ postId }) {
    const [post, setPost] = useState(null);
    const [loading, setLoading] = useState(true);

    useEffect(() => {
        let cancelled = false;

        fetch(`/api/posts/${postId}`)
            .then(r => r.json())
            .then(data => {
                if (!cancelled) {
                    setPost(data);
                    setLoading(false);
                }
            });

        // Cleanup — tránh race condition
        return () => { cancelled = true; };
    }, [postId]); // Chạy lại khi postId thay đổi

    if (loading) return 

Đang tải...

; return

{post.title}

; }

useContext — Tránh Prop Drilling

import { createContext, useContext, useState } from 'react';

const ThemeContext = createContext('light');

function App() {
    const [theme, setTheme] = useState('light');
    return (
        
            
); } // Dùng ở bất kỳ component con nào function Header() { const { theme, setTheme } = useContext(ThemeContext); return ( ); }

useRef — Truy Cập DOM Và Giá Trị Bền Vững

function SearchInput() {
    const inputRef = useRef(null);

    // Focus input khi mount
    useEffect(() => {
        inputRef.current?.focus();
    }, []);

    return ;
}

// useRef lưu giá trị không trigger re-render
function Timer() {
    const intervalRef = useRef(null);

    const start = () => {
        intervalRef.current = setInterval(() => {
            console.log('tick');
        }, 1000);
    };

    const stop = () => clearInterval(intervalRef.current);
}

useMemo Và useCallback — Tối Ưu Performance

// useMemo — cache kết quả tính toán nặng
const expensiveValue = useMemo(() => {
    return heavyCalculation(data);
}, [data]); // Chỉ tính lại khi data thay đổi

// useCallback — cache hàm để tránh child re-render
const handleSubmit = useCallback((values) => {
    api.submit(values);
}, []); // Hàm này không bao giờ thay đổi

Custom Hooks — Tái Sử Dụng Logic

function useFetch(url) {
    const [data, setData] = useState(null);
    const [loading, setLoading] = useState(true);
    const [error, setError] = useState(null);

    useEffect(() => {
        fetch(url)
            .then(r => r.json())
            .then(setData)
            .catch(setError)
            .finally(() => setLoading(false));
    }, [url]);

    return { data, loading, error };
}

// Dùng ở bất kỳ đâu
function PostList() {
    const { data: posts, loading } = useFetch('/api/posts');
    if (loading) return 

Loading...

; return posts.map(p =>
{p.title}
); }
Dependency array của useEffect là nguồn gốc của 90% bugs với hooks. Nếu bạn bỏ sót dependency, component sẽ dùng giá trị cũ. Luôn dùng eslint-plugin-react-hooks để cảnh báo.

Kết Luận

Nắm vững 4 hook cơ bản (useState, useEffect, useContext, useRef) là đủ cho phần lớn use case. useMemo và useCallback chỉ nên dùng khi đã xác định được performance bottleneck — đừng premature optimize.

#React #JavaScript #Frontend #Hooks
a
Tác giả
admin

Lập trình viên, yêu thích chia sẻ kiến thức về công nghệ và phát triển phần mềm.

Bình luận

Chưa có bình luận. Hãy là người đầu tiên!

Để lại bình luận

Bình luận sẽ được duyệt trước khi hiển thị.