Công nghệ

5 Lỗi Thường Gặp Khi Phát Triển React Và Cách Tránh Chúng

5 Lỗi Thường Gặp Khi Phát Triển React Và Cách Tránh Chúng

React là một trong những thư viện phổ biến nhất để xây dựng giao diện người dùng động. Tuy nhiên, chính sự linh hoạt này cũng dẫn đến việc các nhà phát triển, đặc biệt là những người mới, dễ mắc phải một số lỗi cơ bản.

Trong bài viết này, chúng ta sẽ cùng khám phá 5 lỗi thường gặp khi phát triển React và tìm hiểu cách khắc phục để cải thiện chất lượng mã và hiệu suất ứng dụng.

1. Thay đổi trực tiếp State (Mutating State)

Hãy xem xét một ví dụ đơn giản: một React component hiển thị danh sách các mục và cho phép thêm hoặc xóa mục:

import { useState } from "react";  

const Home = () => {  

    const [items, setItems] = useState(['item1', 'item2']);  

    const [itemToAdd, setItemToAdd] = useState('');  

    function wrongHandleAddItem(item) {  

        items.push(item);  

        setItems(items);  

    }  

    function goodHandleAddItem(item) {  

        if (item.length === 0) return;  

        const newArray = [...items, item];  

        setItems(newArray);  

        setItemToAdd('');  

    }  

    function removeItem(item) {  

        const itemIndex = items.indexOf(item);  

        if (itemIndex !== -1) {  

            const newArray = [...items];  

            newArray.splice(itemIndex, 1);  

            setItems(newArray);  

        }  

    }  

    return (  

        <div style={{ padding: '3rem', maxWidth: '12rem' }}>  

            <div>  

                {items.map((item, key) => (  

                    <div key={key} style={{ marginTop: '0.5rem', display: 'flex', justifyContent: 'space-between' }}>  

                        {item}  

                        <button onClick={() => removeItem(item)}>-</button>  

                    </div>  

                ))}  

            </div>  

            <div style={{ marginTop: '1rem' }}>  

                <input value={itemToAdd} onChange={event => setItemToAdd(event.target.value)} />  

                <button onClick={() => wrongHandleAddItem(itemToAdd)} style={{ marginLeft: '1rem' }}>+</button>  

            </div>  

        </div>  

    );  

};  

export default Home;  

 

Phân tích

  • Trong hàm wrongHandleAddItem, chúng ta sử dụng phương thức push để thêm mục mới vào mảng items. Tuy nhiên, hành động này thay đổi trực tiếp mảng. Sau đó, khi gọi setItems(items), React không nhận diện được sự thay đổi, do đó không cập nhật lại giao diện.
  • Lý do: React dựa vào identity (định danh) của biến state để xác định khi nào cần cập nhật. Thay đổi nội dung mà không thay đổi định danh của mảng sẽ không kích hoạt re-render.

Cách sửa

Sử dụng toán tử spread () để tạo một mảng mới, sau đó cập nhật state:

 

function goodHandleAddItem(item) {  

    if (item.length === 0) return;  

    const newArray = [...items, item];  

    setItems(newArray);  

    setItemToAdd('');  

}  

2. Không sử dụng key trong danh sách

React yêu cầu mỗi phần tử trong một danh sách phải có một key duy nhất. Ví dụ:

 

items.map((item) => (  

    <div>  

        {item}  

        <button onClick={() => removeItem(item)}>-</button>  

    </div>  

));  

Lỗi

Khi không có key, React không thể theo dõi chính xác từng phần tử trong danh sách, dẫn đến các hành vi không mong muốn khi thêm, xóa hoặc cập nhật danh sách.

Cách sửa

  1. Sử dụng chỉ số (index) làm key:
items.map((item, index) => (  

    <div key={index}>  

        {item}  

        <button onClick={() => removeItem(item)}>-</button>  

    </div>  

));  

 

  1. Sử dụng giá trị id duy nhất:
const newItem = { id: crypto.randomUUID(), value: item };  

const newArray = [...items, newItem];  

setItems(newArray);  




items.map((item) => (  

    <div key={item.id}>  

        {item.value}  

        <button onClick={() => removeItem(item)}>-</button>  

    </div>  

));  

 

3. Dùng async trong useEffect

Khi gọi API trong useEffect, chúng ta cần xử lý các thao tác bất đồng bộ một cách cẩn thận. Ví dụ:

 

useEffect(async () => {  

    const res = await fetch("/api/to/fetch");  

    const data = await res.json();  

    console.log(data);  

}, []);  

Lỗi

useEffect không chấp nhận các hàm bất đồng bộ (async). Kết quả là nhận được lỗi:

destroy is not a function  

 

Cách sửa

Tách logic bất đồng bộ vào một hàm khác bên trong useEffect:

useEffect(() => {  

    async function fetchData() {  

        const res = await fetch("/api/to/fetch");  

        const data = await res.json();  

        console.log(data);  

    }  




    fetchData();  

}, []);  

 

4. Truy cập state trước khi re-render

Cập nhật state trong React là bất đồng bộ. Điều này có thể dẫn đến lỗi khi cố gắng truy cập giá trị mới của state ngay sau khi gọi hàm setState.

Ví dụ sai

setItems([...items, newItem]);  

console.log(items); // Giá trị cũ của items sẽ được in ra  

 

Cách sửa

Sử dụng giá trị đã biết, thay vì dựa vào state chưa được cập nhật:

 

const updatedItems = [...items, newItem];  

setItems(updatedItems);  

console.log(updatedItems);  

5. Sử dụng state cũ (stale state)

Một vấn đề phổ biến khác là sử dụng giá trị cũ của state trong các cập nhật liên tiếp:

setCount(count + 1);  

setCount(count + 1);  

Lỗi

Do React gộp các cập nhật state lại, cả hai lần gọi đều sử dụng giá trị cũ của count.

Cách sửa

Sử dụng hàm callback của setState để đảm bảo giá trị mới được cập nhật dựa trên giá trị trước đó:

 

setCount((prev) => prev + 1);  

setCount((prev) => prev + 1);  

Kết luận

Tránh những lỗi này không chỉ giúp bạn viết mã React tốt hơn mà còn tăng hiệu suất ứng dụng đáng kể.

Hy vọng bài viết này hữu ích cho bạn. Chúc bạn học React vui vẻ và thành công! 

Bạn có gặp lỗi nào khác? Hãy chia sẻ cùng mọi người nhé! 

Shares:

Related Posts

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *