0
0
Lập trình
Harry Tran
Harry Tran106580903228332612117

Hướng Dẫn Tạo Hook useFocus() trong React

Đăng vào 2 tháng trước

• 4 phút đọc

Giới Thiệu

Trong lĩnh vực phát triển ứng dụng web, việc quản lý trạng thái của các phần tử là rất quan trọng. Một trong những khía cạnh không thể thiếu là khả năng tập trung (focus) vào các phần tử con trong một component cha. Trong bài viết này, chúng ta sẽ cùng nhau tìm hiểu cách tạo một hook useFocus() trong React, cho phép điều kiện hóa việc render dựa trên trạng thái focus của các phần tử con.

Nội Dung Chính

Cấu Trúc Hook useFocus()

Hook useFocus() sẽ trả về một ref và một boolean để xác định xem các phần tử con có đang được focus hay không. Dưới đây là cấu trúc cơ bản của hook này:

typescript Copy
import React, { Ref, useEffect, useRef, useState } from 'react';

export function useFocus<T extends HTMLElement>(): [Ref<T>, boolean] {
    // code của bạn ở đây
}

Bước 1: Khởi Tạo Ref và State

Trước tiên, chúng ta cần khởi tạo một ref cho input và một state để theo dõi trạng thái focus:

typescript Copy
const ref = useRef<T>(null);
const [isFocused, setIsFocused] = useState(false);

isFocused sẽ là một biến boolean để xác định xem input có đang được focus hay không.

Bước 2: Lấy Node Từ Ref

Tiếp theo, chúng ta sẽ lấy node từ ref. Nếu không có node, chúng ta sẽ trả về null:

typescript Copy
const node = ref.current;
if (!node) return;

Bước 3: Hàm Xử Lý Focus

Chúng ta cần định nghĩa một hàm để đặt isFocused thành true khi có focus vào container hoặc bất kỳ phần tử con nào:

typescript Copy
const handleFocusIn = () => setIsFocused(true);

Bước 4: Hàm Xử Lý Mất Focus

Tương tự, chúng ta cũng cần một hàm để đặt isFocused thành false khi mất focus:

typescript Copy
const handleFocusOut = (e: FocusEvent) => {
    if (node && !node.contains(e.relatedTarget as Node)) {
        setIsFocused(false);
    }
};

Bước 5: Thêm Event Listeners

Chúng ta sẽ thêm các listeners cho sự kiện focusin và focusout vào node:

typescript Copy
node.addEventListener("focusin", handleFocusIn);
node.addEventListener("focusout", handleFocusOut);

Bước 6: Dọn Dẹp Event Listeners

Cuối cùng, chúng ta cần một hàm để dọn dẹp các event listeners đã đăng ký khi component được render lại:

typescript Copy
return () => {
    node.removeEventListener("focusin", handleFocusIn);
    node.removeEventListener("focusout", handleFocusOut);
};

Mã Hoàn Chỉnh

Dưới đây là mã hoàn chỉnh cho hook useFocus():

typescript Copy
import React, { useRef, useEffect, useState, Ref } from 'react';

export function useFocus<T extends HTMLElement>(): [Ref<T>, boolean] {
    const ref = useRef<T>(null);
    const [isFocused, setIsFocused] = useState(false);

    useEffect(() => {
        const node = ref.current;
        if (!node) return;

        const handleFocusIn = () => setIsFocused(true);
        const handleFocusOut = (e: FocusEvent) => {
            if (node && !node.contains(e.relatedTarget as Node)) {
                setIsFocused(false);
            }
        };

        node.addEventListener("focusin", handleFocusIn);
        node.addEventListener("focusout", handleFocusOut);

        return () => {
            node.removeEventListener("focusin", handleFocusIn);
            node.removeEventListener("focusout", handleFocusOut);
        };
    }, []);
    return [ref, isFocused];
}

export function App() {
    const [ref, isFocused] = useFocus<HTMLDivElement>();
    return <div ref={ref}>
        <input placeholder="Nhập vào đây" />
        {isFocused && <p>Đang được focus</p>}
    </div>;
}

Thực Hành Tốt Nhất

  • Sử dụng TypeScript: Đảm bảo rằng bạn sử dụng TypeScript để có sự an toàn về kiểu dữ liệu. Điều này giúp giảm thiểu lỗi và cải thiện khả năng bảo trì mã nguồn.
  • Dọn Dẹp Event Listeners: Đừng quên dọn dẹp các event listeners để tránh rò rỉ bộ nhớ.

Những Lỗi Thường Gặp

  • Không có Node: Kiểm tra kỹ việc lấy node từ ref, nếu node không tồn tại có thể gây ra lỗi.
  • Lỗi TypeScript: Đảm bảo các kiểu dữ liệu được định nghĩa chính xác để không gặp phải lỗi biên dịch.

Mẹo Tối Ưu Hiệu Suất

  • Tránh sử dụng hook này cho các phần tử không cần thiết để giảm thiểu tải cho DOM.
  • Sử dụng React.memo để tối ưu hóa lại việc render cho các component.

Kết Luận

Hook useFocus() là một công cụ mạnh mẽ giúp quản lý trạng thái focus trong các ứng dụng React. Hy vọng với hướng dẫn này, bạn có thể áp dụng vào dự án của mình một cách hiệu quả. Hãy thử nghiệm và chia sẻ trải nghiệm của bạn với chúng tôi!

Câu Hỏi Thường Gặp

1. useFocus() có thể sử dụng cho loại component nào?

Hook này có thể sử dụng cho bất kỳ loại component nào cần theo dõi trạng thái focus.

2. Có cần phải sử dụng TypeScript không?

Mặc dù không bắt buộc, nhưng việc sử dụng TypeScript giúp tăng cường tính an toàn và dễ bảo trì cho mã nguồn.

3. Làm thế nào để kiểm tra hook này?

Bạn có thể kiểm tra hook này trong môi trường phát triển React hoặc sử dụng unit tests để đảm bảo tính chính xác.

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào