9

Tìm hiểu về Recoil - thư viện quản lý state trong ReactJS

đăng cách đây 1 tháng

Xin chào mọi người, xin chào các con chiên của ReactJS, hẳn trong thời gian làm việc với thư viện frontend quốc dân này các bạn cũng kinh qua một vài cách quản lý state của hắn chẳng hạn như Redux, MobX hoặc thậm chí có người hardcore hơn là dùng Context API hoặc dùng thuần lifting up state, vân vân và mây mây.

Data Graph RecoilData Graph Recoil

Nhân tiện hôm nay đang rảnh rỗi cộng thêm việc sắp tới có presentation về công nghệ mới, mình chia sẻ tới mọi người về một thằng thư viện quản lý state của Facebook, gọi là RecoilJS, ghê chưa ghê chưa ? À mà khoan, từ từ đã, đã là con ruột sao thằng này vẫn chưa được nhắc đến trong official docs của ReactJS ?


Theo mình chầm chậm tìm hiểu, thì đến thời điểm mình viết bài này thì RecoilJS vẫn nằm trong source git facebookexperimental  và vẫn chưa có phiên bản chính thức, hiện tại vẫn là version 0.1.2

Mình để cái link này cho các bạn dễ xem https://www.npmjs.com/package/recoil

tuy vậy hiện tại các bạn vẫn có thể cài đặt để sử dụng thông qua lệnh

hoặc

Và theo "nghe ngóng" từ David McCabe ( co-author của Recoil ) thì thư viện này đã và đang được dùng trong một vài tools nội bộ của Facebook và vẫn đang được phát triển bởi team của David, chứ không phải từ team core của ReactJS, hmm, mà thôi ngại gì mà không shoutout cho anh một phát nào.

✧ ✧ ✧

Về bundle size

Mình so sánh 3 thằng là Redux, MobX, Recoil

Này là của ReduxNày là của Redux
Này là của MobXNày là của MobX
Cuối cùng là RecoilCuối cùng là Recoil

So với 2 người đàn anh đi trước thì Recoil bundle size thấp hơn MobX một tí, và nặng gấp 6 lần Redux, nhưng mà bạn không cần phải cài thêm bất kì lib nào khác để connect với React nên về bundle size như vậy cũng khá là dễ hiểu, tất cả trong một mà. Có lẽ ở những version tiếp theo, team Recoil sẽ optimize lại phần này.

✧ ✧ ✧

Giới thiệu chung

Recoil được sinh ra để giải quyết những vấn đề chính đang hiện hữu trong cách quản lý state truyền thống của React là:

  • Nếu dùng lifting update state thì state tree sẽ rất dài, khó quản lý, cộng thêm nữa state phải đưa lên root parent component để rải xuống cho đàn con
  • Nếu dùng Context API thì mỗi Context Provider chỉ chứa được một single value, khó tách ra để quản lý, mà muốn dùng nhiều Context thì phải wrap nhiều Provider lồng vào nhau. Hell nooooo

Recoil sẽ giúp cho việc code-split được dễ dàng hơn giữa state store và component sử dụng nó, theo anh Dave thì base của Recoil dựa trên concept Multiple Context, nghe có vẻ hấp dẫn nhỉ, nhưng nhìn có vẻ cũng không khác gì Redux. Hihi, nhưng mà cách setup của Recoil thì mình thấy là đơn giản hơn rất nhiều.

EasyyyyEasyyyy

Recoil giúp bạn tạo ra một sơ đồ luồng dữ liệu chạy từ các Atoms (nguyên tử) chứa state qua các Selectors ( là pure function ) đổ xuống các component cần sử dụng. Atoms là các đơn vị state mà component có thể lấy ra sử dụng. Selectors là các pure function tính toán value từ Atoms một cách đồng bộ hoặc bất đồng bộ.

Atoms ??? Là cái gì vậy trời ??? Tôi có muốn học hoá ở đây đâu :(. Thôi đọc tiếp vậy.

✧ ✧ ✧

Atoms

Atom ở đây mình hiểu đơn giản là một phần tử chứa state với unique keyvalue

Component chỉ cần truy suất vào những Atoms mình cần để lấy value cần dùng

Mình có làm một demo về phép toán cộng đơn giản cho các bạn hiểu chứ nói lý thuyết nhiều thì hay bị bảo là "thằng lý lẽ" :(

Đây là source tree của demoĐây là source tree của demo

Ở file App.js mình wrap ở ngoài tất cả các component sẽ cần truy xuất tới Recoil Atoms và Selectors bằng RecoilRoot

App.jsApp.js

Tiếp theo mình define các atoms gồm 1 atom chứa giá trị số hạng thứ nhất và 1 atom cho số hạng thứ 2, mình bỏ vào file atoms.js.

Key của mỗi atom phải là unique, và sẽ có default là giá trị khởi tạo

atoms.jsatoms.js

Mình sẽ tạo 2 components FirstNumber và SecondNumber sẽ là những input elements truy suất và update value 2 số hạng này

FirstNumber.jsFirstNumber.js

Các bạn có thể thấy component sẽ dùng hook api useRecoilState để lấy ra value và modify function tương tự như useState của React, rất dễ.

Selectors

Các selectors bản chất là chứa phần xử lý logic và tính toán dựa trên input là value từ các atoms hay selectors khác và trả về kết quả mong muốn, cũng không thể modify value của selectors từ bên ngoài nên nếu component muốn truy suất thì phải dùng hook api là useRecoilValue

Ở đây là selectors.js thì mình sẽ tạo 1 selector chứa giá trị tổng

selectors.jsselectors.js

Có thể thấy input là 2 số hạng lấy thông qua hàm get

Và ở file Total.js chứa component Total mình sẽ lấy giá trị từ selector bằng useRecoilValue

Total.jsTotal.js

Và sau đây mình có kết quả là

kết quả kết quả

Như lúc đầu mình đã có đề cập đến Asynchronous trong các Selectors, vậy thì mình thử thay đổi một tí trong total selector xem sao nha

Mình thêm vào một PromiseMình thêm vào một Promise

Như các bạn thấy mình đã thêm vào một Promise để giả lập việc Async và kèm theo async await để lấy value trả về, nhưng tại vì việc render trong React là Synchronous nên lúc này file Total.js sẽ bị báo lỗi, và may quá lúc này Recoil cho phép mình dùng React Suspense để xử lý pending data.

App.jsApp.js

Kèm theo Suspense là một fallback trong trường hợp pending

Và kết quả là

HurayyyyHurayyyy
✧ ✧ ✧

Testing

Hiện tại theo mình biết thì có 2 cách là dùng Jest Mock hoặc tạo một Component wrapper lấy value từ Recoil và truyền dưới dạng prop xuống component cần test và thực hiện testing bình thường

Điểm mình thích

  • Setup đơn giản hơn các library quốc dân khác (Redux, MobX)
  • Tất cả trong một thư viện
  • Tương thích và thân thiện với React API
  • Data Store được đưa lên Global, được Distributed ra thành nhiều atom khác nhau, dễ dàng được truy suất từ tất cả các cấp component mà không cần dồn một "cục" vào Single Object như Redux

Nhược điểm

Hiện tại bản thân mình thấy Recoil vẫn chưa sẵn sàng để mình apply vào sản phẩm tại vì những lí do sau:

  • Vẫn chưa support Server Side Rendering
  • Vẫn chưa có extension để debug hoặc visualize data graph như Redux Devtool
  • Và vẫn chưa có bản release chính thức
✧ ✧ ✧

Okay vậy thôi, cảm ơn các bạn đã đọc bài, mong được nhận nhiều đóng góp từ các bạn, link demo mình có để ở dưới , các bạn có thể tham khảo nha :D

Thanks guys and peace out !!!

✧ ✧ ✧
#reactjs#javascript#recoiljs
9
0
...