useEffect
là một trong những hook quan trọng và được sử dụng phổ biến trong các dự án React.
Để hiểu rõ hơn về tác dụng của useEffect
, bạn có thể đọc lại bài viết này.
Vì useEffect
thường được sử dụng nhiều, nên việc viết mã trong hook này một cách cẩn thận là quan trọng. Một code không tốt có thể khiến dự án trở nên khó đọc và tăng nguy cơ gặp lỗi tiềm ẩn.
Bài viết này sẽ chia sẻ một số nguyên tắc để làm việc với useEffect
một cách hiệu quả hơn, giúp mã nguồn trở nên dễ quản lý hơn.
1. Viết ít effect hơn
Để tối ưu mã nguồn và tránh những lỗi không mong muốn, việc giảm thiểu sử dụng các effects khi làm việc với state là một nguyên tắc cơ bản.
Cũng như với hook useEffect, việc hạn chế sử dụng nó là quan trọng để duy trì sự đơn giản và hiệu quả của mã nguồn. Nếu có thể giảm bớt sự phụ thuộc vào useEffect hoặc tìm kiếm các giải pháp thay thế, điều này giúp tăng cường hiệu suất và dễ dàng bảo trì mã nguồn.
Tuy nhiên, không tránh khỏi những trường hợp cụ thể mà bạn phải sử dụng hook useEffect, như khi cần lấy dữ liệu ban đầu cho một màn hình cụ thể khi nó được khởi tạo. Trong những tình huống như vậy, sự linh hoạt của useEffect trở nên quan trọng, đảm bảo rằng các tác vụ cần thiết được thực hiện đúng cách mà không làm giảm hiệu suất chung của ứng dụng.
Data fetching
Data fetching là một side effect phổ biến thường được quản lý bằng useEffect(). Về cơ bản, các ứng dụng kiểu SPA đều phải lấy dữ liệu từ server. Do đó, data fetching là công việc phổ biến tới mức có rất nhiều thư viện 3rd được viết ra để tối ưu hóa chúng.
Có một số thư viện như react-query, Apollo… mà bạn có thể thử. Với những thư viện, bạn sẽ hạn chế tối đa phải sử dụng tới useEffect.
2. Tuân theo nguyên tắc single responsibility principle
Nếu bạn đã từng đọc về bộ triết lý để viết code clean có tên S.O.L.I.D thì sẽ biết ngay nguyên tắc này.
Nội dung nguyên tắc này là: Mỗi class, mỗi function chỉ nên làm một việc duy nhất, không nên kiêm nhiệm nhiều việc.
Nguyên tắc này cũng tương tự khi áp dụng với hàm trong useEffect()
, không nhồi nhét nhiều thứ vào một lần gọi useEffect.
Ví dụ: chúng ta có một lần dùng useEffect như sau:
- React.useEffect(() => {
- document.title = ‘hello world’
- trackPageVisit()
- }, [])
Như ở đây, mỗi khi component được mounted, bạn sẽ thực hiện hai việc là: gán tiêu đề “hello world” cho trang và theo dõi lượt visit trang.
Như vậy là bạn đã thực hiện 2 việc rất khác nhau trong lần sử dụng useEffect này. Hiện tại thì chúng ta có thể tặc lưỡi bỏ qua vì nó cũng vẫn đơn giản. Nhưng khi chức năng phần mềm phức tạp dần lên theo năm tháng thì sao?
Ví dụ chúng ta muốn thêm tính năng đồng bộ state với tiêu đề trang, mỗi khi state thay đổi thì tiêu đề trang sẽ tự động cập nhật theo:
- const [title, setTitle] = React.useState(‘hello world’)
- React.useEffect(() => {
- document.title = title
- trackPageVisit()
- }, [title])
Bạn đã nhận ra bug bắt đầu xuất hiện ở đây chưa?
Bug ở đây là mỗi khi tiêu đề trang thay đổi (vì một lý do nào đó như thay đổi cài đặt) thì hàm trackPageVisit()
cũng bị gọi và dẫn đến làm sai số liệu lượt visit trang.
Để xử lý lỗi này, đơn giản là tách ra làm hai lần gọi effect thôi:
- const [title, setTitle] = React.useState(‘hello world’)
- React.useEffect(() => {
- document.title = title
- }, [title])
- React.useEffect(() => {
- trackPageVisit()
- }, [])
Bạn thấy đấy, code vừa dễ đọc, vừa tránh được lỗi lại vừa dễ quản lý khi sau này yêu cầu chức năng có phức tạp hơn.
3. Viết custom hook
Thực sự mà nói, mình không thích những component mà nhồi nhét quá nhiều hook, chưa kể trong mỗi hook lại có quá nhiều công việc trong đó. Vì cách viết như này sẽ trộn lẫn giữa logic nghiệp vụ và các chỉ dấu – markup.
Bạn hoàn toàn có thể refectoring lại chỗ này cho code được đẹp hơn, bằng cách viết custom hook. Đặc biệt, các custom hook còn có thể tái sử dụng.
Dưới đây là một số ưu điểm của custom hook.
Có thể đặt tên hook theo ý muốn
Việc đặt tên cho hook của bạn một cách thông minh có thể làm cho mã nguồn trở nên rõ ràng và dễ đọc hơn đáng kể. Thay vì chỉ sử dụng useEffect và chứng kiến một loạt các logic bên trong nó, việc sử dụng một hook có tên mô tả rõ chức năng sẽ giúp các nhà phát triển mới đọc và hiểu mã nguồn một cách dễ dàng hơn.
Dưới đây là một ví dụ về đặt tên cho custom hook. Chỉ cần nhìn tên là biết hook này định làm gì.
- const useTitleSync = (title: string) => {
- React.useEffect(() => {
- document.title = title
- }, [title])
- }
- const useTrackVisit = () => {
- React.useEffect(() => {
- trackPageVisit()
- }, [])
- }
Đóng gói logic
Đây có lẽ là lợi thế lớn nhất của custom hook. Khi mà mọi logic được đóng gói hoàn chỉnh, khi cần là gọi sử dụng.
Như ví dụ trên, useTitleSync
hook vẫn chưa hoàn chỉnh lắm, khi mà nó chỉ đóng gói được phần đánh dấu effect, khi mà component nào sử dụng vẫn phải quản lý thủ công phần tiêu đề. Vậy tại sao chúng ta không đưa luôn phần quản lý tiêu đề vào trong hook này?!
- const useTitle = (initialTitle: string) => {
- const [title, setTitle] = React.useState(initialTitle)
- React.useEffect(() => {
- document.title = title
- }, [title])
- return [title, setTitle] as const
- }
Dễ unit test
Nói đến clean code thì không thể nhắc tới việc phải dễ unit test.
Việc chúng ta đã tách được custom hook ra khỏi logic của component sẽ khiến việc test custom hook giống như bao function bình thường khác. Khi test, bạn sẽ không còn phải quan tâm tới các logic khác của component như trackingPageVisit
.
- import { act, renderHook } from ‘@testing-library/react-hooks’
- describe(‘useTitle’, () => {
- test(‘sets the document title’, () => {
- const { result } = renderHook(() => useTitle(‘hello’))
- expect(document.title).toEqual(‘hello’)
- act(() => result.current(‘world’))
- expect(document.title).toEqual(‘world’)
- })
- })
Trên đây là một kinh nghiệm để sử dụng useEffect được hiệu quả, giúp mã nguồn cũng sẽ dễ đọc và hạn chế lỗi tiềm tàng.
Ngoài ra, còn nhiều kinh nghiệm hay khác, bạn có thể tham khảo:
- ReactJS – Khi nào cần sử dụng tới useCallback?
- Nên Học Lập Trình Web Hay Lập Trình Ứng Dụng Di Động
- Loop through an Array in Reverse order using JavaScript
Bạn thấy những kinh nghiệm này thế nào? Có giúp được gì cho dự án của bạn không? Để lại ý kiến chia sẻ với mọi người trong phần bình luận nhé.
Nguồn tham khảo: tkdodo.eu
One thought on ““Nghệ thuật” sử dụng useEffect() được hiệu quả hơn trong React”