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.
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.
Mình so sánh 3 thằng là Redux, MobX, 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.
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à:
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.
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.
Atom ở đây mình hiểu đơn giản là một phần tử chứa state với unique key
và value
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ẽ" :(
Ở 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
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
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
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ễ.
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
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
Và sau đây mình có kết quả là
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
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.
Kèm theo Suspense là một fallback trong trường hợp pending
Và kết quả là
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
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:
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 !!!