Latest Post

Tăng thứ hạng và truy cập tự nhiên với 10 phương pháp SEO hay nhất Kiếm Tiền Online (mmo): Khái Niệm và Các Hình Thức Phổ Biến

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.

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. 1. Viết ít effect hơn
    1. Data fetching
  2.  2. Tuân theo nguyên tắc single responsibility principle
  3. 3. Viết custom hook
    1. Có thể đặt tên hook theo ý muốn
    2. Đóng gói logic
    3. Dễ unit test

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:

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

Trả lời

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 *