Chọn lib state management nào bây giờ?

Tại sao cần đọc bài này?

  • Có một bộ tiêu chí khi chọn library về Frontend State Management
  • State management là làm gì
  • State management thì quan tâm tới những thứ gì
  • Có thêm n lý do để từ bỏ redux
 
Thường những người tìm tới được bài này của mình sẽ thuộc 1 trong 2 nhóm
  1. Frontend engineer đã quá mệt mỏi, suffer với redux 😵‍💫
  1. Các bạn mới bắt đầu làm frontend và muốn tìm hiểu thêm về state management
Nếu các bạn thuộc nhóm 1 thì... Tuyệt vời, mình viết bài này với 80% năng lượng là muốn thoát khỏi redux 😄 . Còn nếu thuộc nhóm 2 thì bài này sẽ giúp các bạn có nhiều góc nhìn hơn về state management, cách để tỏ ra cool ngầu với các anh chị đồng nghiệp :))

State-management là cái *éo gì

notion image
Nếu tìm hiểu về state-management là cái gì trên Google thì có khá nhiều định nghĩa, tuy nhiên đều có thể tóm gọn lại thành 2 ý chính như sau:
  1. ☠️ State là khung xương của application
  1. 🏃 State management ⇒ Quản lý cái khung xương đó
It's fuking simple, right?

FAQ

Khung xương của application?
Là toàn bộ data, trạng thái của applicate để thể hiện ra ui.
Bạn có trạng thái isLoading sẽ render ra Spinner ở ui, isLoading là state
Bạn có trạng thái isLoggedIn để biết user đã đăng nhập hay chưa, isLoggedIn là state
Bạn có một cây DOM để render page profile, nói rộng ra nó cũng là state, chẳng qua là thằng state này là bộ xương có đắp thêm tí thịt.
 
Tại sao cần quản lý state?
Application càng ngày càng phức tạp → càng ngày càng có nhiều state → cần có biện pháp quản lý state
Ngoài ra một lý do nữa khiến việc càng ngày càng có nhiều state vì việc tính toán đang đổ xuống frontend nhiều hơn
Các bác sẽ không muốn lục tìm trong đống code, khi user đăng nhập thì cần tính toán lại những state nào; khi users add một post thì cần đi tìm chỗ stats update lại totalPost,...
Vì vậy cần có cách để quản lý state hiệu quả hơn!
Tao code jQuery thì có quân tâm gì tới state management đâu?
Yup, gần như sau khi react bắt đầu phổ biến thì state-managment mới bắt đầu xuất hiện hàng loạt.
Lý do code jQuery chả có ai nói state management (tuy nhiên các bác vẫn có state và vẫn phải quản lý nó nhé) vì hồi đó state còn đơn giản, các state cũng thường dính vào UI luôn (Qua các thuộc tính data-* ) không tách biệt ra, nên công việc còn đơn giản, mà đơn giản thì đâu cần management mọe gì đâu
Reactjs - A JavaScript library for building user interfaces
React - được định nghĩa là View library, tuy nhiên vẫn có khá nhiều tranh cãi, và mình cũng công nhận là nó sắp không còn là View library nữa rồi, tuy nhiên theo định nghĩa đơn giản nhất thì cứ cho nó là View đi. Nếu vậy thì nó chỉ làm rất tốt việc của nó: Render UI
Okey, các bác sẽ nói, tao có thể dùng setState, useState để quản lý trong state chỉ với React, đúng, nhưng react không tốt nhất trong việc đó. Kinh điển nhất là vấn đề props drilling.
 
 
 
State management chỉ áp dụng cho React?
Không! Theo định nghĩa thì 99,99999% app sẽ có state (0.0000001% là app Helloworld), và nó sẽ có ích cho tất cả các App bắt đầu trở nên phức tạp, không kể thư viện, stacks các bác đang sài là gì.
  • React
  • Vue
  • Flutter
  • Backend, Smart Contract
Tại sao mình thù ghét Redux
Cơ bản thì mình không ghét lắm, mình chỉ thấy nó overrated thôi
Video preview
 
Nếu còn câu hỏi nào, các bác comment bên dưới nhé 👇

Vậy chọn state-management nào?

⚛️
Phần này mình chỉ focus vào React thôi nhé, vì công việc hiện tại của mình đang focus vào React.
Short: Cơ bản các bác không cần state-management library nào cả, React + ReactContext + api query library là đủ 🤷‍♂️
People often choose Redux before they need it. “What if our app doesn’t scale without it?” Later, developers frown at the indirection Redux introduced to their code. “Why do I have to touch three files to get a simple feature working?” Why indeed!
Về cơ bản, hầu hết state của các bác chỉ share trong một feature, do đó sẽ gói gọn trong một route (VD: /users , /posts ). Do đó, với mỗi route, mình chỉ cần có một ReactContext là đủ handle 80% trường hợp.
Một số feature sẽ cần data users, nếu vậy thì mỗi lần đều phải query lại users? Hầu hết các lib query hiện đại solve case này cho các bác bằng cách cache rồi. Hãy thử swr hoặc react-query
Nếu mọi thứ bắt đầu trở nên phức tạp, có thể add thêm các library như Recoiljs, Jotai. Các thư viện này có thể bỏ về và dễ dàng thay thế useState bằng cách Search & Replace.
Đừng phức tạp hóa vấn đề trước khi nó còn đơn giản, chuẩn bị cho sự thay đổi là được.
Long:

Features

https://javascript.plainenglish.io/do-you-know-the-5-types-of-states-in-react-8734a04a5ffb
State cũng có nhiều kiểu khác nhau, nên cũng có nhiều kiểu phân loại khác nhau nhưng mình thấy bài viết này khá ok về việc phân loại state
 
Một số best-practice
  • Form state: Đừng bỏ nó bảo cái global state/store .... gì gì của các bác, nó tốt nhất chỉ nên ở một component thôi. Vì vậy dùng react-hook-form là đủ
  • Navigation state: react-router gần như mặc định có trong mọi project rồi, tốt nhất là nên kệ nó đi. Nếu muốn integrate với global state, thì chiều sync ok nhất là: Navigation state → Global state. Case này hay thấy khi làm trang search có filter đồ
 
 
notion image
Ok còn lại 3 thằng
  1. Logical state
  1. Server state
  1. Browser state
💡
Nghĩa là mình cần tìm một state management library để quản lý Logical state, Server state và Browser state

Easy to add

Một thư viện tốt, đối mới mình là DX phải tốt, mình không muốn tốn nửa ngày chỉ để tìm xem cách gắn nó vào app của mình như thế nào.
Vì đặc thù state-management là một thứ phức tạp, do đó, đương nhiên nó sẽ phức tạp để thêm vào, nhưng đừng làm nó phức tạp hơn nữa ... Redux 😡
Tuy nhiên phần này chỉ cần làm một vài lần khi code một prj mới, do đó, tiêu chỉ này chỉ hơi quan trọng

Easy to write, easy to understand

Đừng bắt mình phải code một use case: Query API → Render list user phải:
  1. Dispatch query action với keyword
  1. Viết reducer nhận query, sau đó dispatch một saga action
  1. Viết sagas action
  1. Viết 2 reducer thêm khi sagas thành công, khi sagas lỗi
  1. Nếu thành công thì merge data nhận được vào cây state
  1. Mapping state ra UI
Đây công việc mà mình thấy de-optimize nhất mà hầu hết frontend engineer phải làm ở thời điểm hiện tại. Đúng là "people make it complicated", một thư viện tốt là thư viện phải giúp dev, enjoy cái moment" này.
Ngoài ra, mình cũng không phải tốn cả ngày để giải thích với một bạn Junior là data sẽ chạy qua những bước này bước này, phải nghe ca thán "nó ngoằng quá a ơi 😭", rồi lỡ đang chỉ xong không chạy được thì phải ngồi debug cho bằng ra thì thôi cho khỏi quê.
💡
Do đó easy to write cũng đồng nghĩa với việc easy to understand

Community = Easy to debug/enhance

Community không phải tự nhiên mà luôn là tiêu chí ai cũng quan tâm khi lựa chọn Library, Framework, ....etc
Community là phần có thể cover easy to write, easy to read rất nhiều.
Làm theo doc không add được lib → search google → copy/paste → done. Không viết được → search google → copy/paste → done.
Do đó sức mạnh của một library đến từ cộng đồng support nó, và Redux đang on-top ở khoản này

Performance

Thường thì các library dạng core như này không thể, hoặc rất rất khó khi muốn thay thế bằng library khác. Trong khoảng khắc bạn nhận ra: "cái library này chạy chậm vl, éo optimize được" và mình cũng "không thể thay bằng thằng khác được nữa"
Do đó Performance là tiêu chí cần cân nhắc khi đây là prj lâu dài và có tương lai sẽ mở rộng rất lớn.
Về performance có thể chia nhỏ thành 2 tiêu chí:
  1. Load time - thường phụ thuộc vào library size, network,...
  1. Interactive time - thường phụ thuộc vào "nội tại" của library đó
Mảng state-management này tập trung chủ yếu vào việc xử lý data, nên phần Interactive time là quan trọng hơn cả. Đặc biệt trong context react, bạn cần chú ý tới việc trigger re-render component khi state được update
notion image
 
⚠️
Nếu prj của bạn vào dạng vừa và nhỏ thì không nên quan tâm tới vấn đề này nhé. Mình nghĩ tầm dự án này thì nên quan tâm việc code sao cho nhanh, dễ hiểu là được. Optimize rồi mà chỉ chạy nhanh hơn 10ms thì không đáng đánh đổi đâu Mình đã phải ngồi fix rất nhiều bug nhỏ nhỏ và không đoán trước được vì ông code trước đó focus vào optimize quá sớm!

Phù hợp với project dạng nào

Không phải tự nhiên mà có rất rất nhiều state-management library, đơn giản vì 2 lý do:
  1. Họ quá mệt với Redux rồi 😫
  1. Tùy vào project có độ phức tạp khác nhau mà sẽ có những tradeoff phù hợp → tạo ra library phù hợp với tradeoff đó
👉
Đây là tiêu chí quan trọng nhất mà mình thấy khác biệt giữa một người "đam mê công nghệ" và một người "đam mê công nghệ thực dụng". Khi đi làm thì mình có gặp một số người rất thích công nghệ mới, cái này mới ra xịn quá nhưng vô tình quên mất, cái xịn sò đó chả bao giờ apply ở project đang chạy cả, đôi khi nó còn là nhân tố de-optimize 🙃

Result

Đây là kết quả đánh giá của mình sau khi đã làm project thật với một số thư viện top trong mảng này, tuy nhiên đây chỉ là góc nhìn cá nhân do your own research.
Name
Easy to add
Easy to Write/ Easy to understand
Community
Type of project
Comment
Redux
3
2
10
Super complex, super big
Mobx, Mobx State Tree
6
6
7
Medium to big
Reactive, vue like state-managemnt
Recoiljs, Jotai
7
7
4
Small to big
New approach
DVA, zustand
5
6
7
Medium to big
Redux alternative
React context
9
8
10
Small to medium
🚫
Please! Đừng dùng Redux nữa - Redux chỉ handle tốt thằng Logical state - Nếu muốn thêm server state, thêm redux-saga, hoặc redux-thunk vào nhé! Đồng thời tốn thêm 1 ngày đọc document xem tụi nó là gì. 1 ngày đẻ gắn tụi nó vào với nhau, và 1 tuần để debug sao lại không chạy 🙂 - Gắn vào react? Cài thêm redux-react - App sau một thời gian code sml thì nó chạy chậm? Gắn thêm reselect Quá nhiều thứ phải đọc, quá nhiều thứ phải code để quản lý state. Thực tế làm việc của mình thì redux là nhân tố de-optimize nhất trong stack frontend 🦥
notion image
 
Hy vọng qua bài này các bác có thêm góc nhìn overview về state-management và cụ thể là state-managment trong react. Và đặc biệt, please, đừng dùng redux nếu nó không phù hợp nữa
 
 
 

Loading Comments...

Follow me @thanhledev

Xin lỗi các bạn vì thời gian qua mình không dành thời gian viết nhiều. Dạo này mình khá bận cho dự án https://getnimbus.io. Check it out 🥳