Nếu bạn nào đã từng sử dụng qua React chắc hẳn sẽ gặp phải những rắc rối với việc quản lý các global state, một trong những giải pháp mà đa số mọi người hay dùng đó là sử dụng Redux và bạn phải wrap mọi React component bằng higher-order connect() component, việc setup một React project với Redux trước đây khá là phức tạp. Nhưng từ bản React 16.8 thì hooks đã được cập nhật thêm vào và sau đó thì team Redux cũng đã cập nhật thêm vào thư viện React Redux của mình các hook mới và có thể thay thế cho việc dụng connect() như trước đây.
Functional vs Class-Component
Chúng ta đều đã biết để định nghĩa một component trong React thì cách đơn giản nhất là sử dụng một Javascript function, function này đơn giản chỉ là nhận vào props và trả về một React element:
1 | function Welcome(props) { |
Tuy nhiên bạn cũng có thể sử dụng cú pháp trong ES6 để tạo ra một component giống vậy
1 | class Welcome extends React.Component { |
Cả 2 cách trên đều cho chúng ta cùng một kết quả như nhau, nhưng ở đây có vài điểm khác biệt là trong class component thì bạn có thể tạo ra các state và handle việc render lại view thông qua hàm setState và sử dụng các hàm trong lifecycle được thừa kế từ React component, còn functional component thì không thể hay nói cách khác nó là stateless.
Sự ra đời của React hook
Bởi vì functional component thì dễ dàng hơn cho việc đọc code cũng như viết test bởi vì nó không có các thành phần state hoặc lifecycle như trong class component, bạn có thể dễ dàng tách rời view với các xử lý logic. Nhưng thứ tuyệt vời hơn mà mọi developer đều mong muốn đó là bạn sẽ được code ít hơn 😎 và thứ mà người dùng mong muốn là performance của ứng dụng sẽ được tăng lên đáng kể. Một ví dụ dễ thấy trong trường hợp này là việc Facebook rebuild lại app Messenger của mình trên nền tảng IOS, họ đã giảm từ 1,7 triệu dòng code xuống còn 360.000 dòng và giờ đây ứng dụng của họ nhẹ hơn 1/4 và phản hồi nhanh hơn gấp đôi so với trước đây.
Tuy nhiên functional component trong React lại không hỗ trợ state và thiếu đi các phương thức trong lifecycle, đó chính là lý do cho sự ra đời của React hook một trong những bổ sung quan trọng trong bản React 16.8 đó là sự góp mặt của hook-state và hook-effect.
- Để sử dụng hook-state ta gọi hàm useState() trong React với tham số truyền vào là giá trị khởi tạo ban đầu của state và hàm này sẽ trả về một cặp giá trị bao gồm giá trị state hiện tại và một hàm để cập nhật state mới. Hook này thay thế cho hàm setState() được sử dụng trong class component.
1 | const [time, setTime] = useState(new Date()) |
- Để sử dụng hook-effect ta gọi hàm useEffect() trong React với tham số truyền vào là một function (thay thế cho componentDidMount) và có thể trả về một function (thay thế cho componentWillUnMount). Hook này được dùng để thay thế cho các phương thức trong lifecyle được sử dụng trong class component, nó được gọi mỗi khi Dom được cập nhật.
1 | const changeTime = () => { |
Sự kết hợp React với Redux Toolkit thông qua react-redux
Như mình đã đề cập ở trên thì sau khi React hook ra đời team Redux họ cũng đã update thêm vào thư viện react-redux của mình hai hook quan trọng là useSelector() và useDispatch() thay thế cho hàm connect() trước đây để lấy các state từ store ra và dispatch actions để cập nhật lại store.
Vậy thì còn Redux Toolkit là cái gì nữa, trước đây khi chưa có nó thì để quản lý được state trong Redux chúng ta cần tạo ra một reducer với giá trị state khởi tạo và các hàm để cập nhật lại state, tiếp tục tạo ra các actions tương ứng với các hàm thay đổi state, việc này khá là mất thời gian và hơn nữa mỗi lần muốn cập nhật state chúng ta phải clone ra một state mới chứ không thể mutate state trực tiếp được. Vì vậy mà team Redux họ đã tạo ra Redux Toolkit, mục đích chính là để đơn giản hoá việc cấu hình Redux store, loại bỏ bớt các boilerplate code và bổ sung thêm vào các package hữu ích cho developer như redux-thunk, Redux Devtool. Cung cấp các api createReducer() và createAction giúp việc tạo ra các reducers và actions dễ dàng hơn với khả năng mutate state trực tiếp thông qua thư viện immer được tích hợp sẵn. Bạn có thể tìm hiểu thêm nhiều tính năng mới hữu ích về Redux Toolkit ở đây [link].
Một trong những api mà mình thích nhất khi sử dụng Redux Toolkit đó là createSlice(), nó nhận vào một list các hàm cập nhật state dưới dạng object, một slice name và một giá trị khởi tạo cho state. Chúng ta sẽ nhận lại được đồng thời reducer và các actions tương ứng, rất gọn gàng và dễ đọc.
1 | const counterSlice = createSlice({ |
Tóm lại mình thấy rằng React hook ra đời là một điều cần thiết và điều đó cũng không có nghĩa là class component sẽ bị khai tử, chính Facebook họ cũng thừa nhận rằng họ không hề có ý định làm điều đó mà React hook ra đời với khả năng tương thích ngược, có nghĩa là bạn vẫn có thể sử dụng class component cho dự án của mình nếu như trước giờ bạn đang làm việc với nó. Nhưng nếu bạn đang chuẩn bị build một ứng dụng khác bằng React thì hãy cân nhắc cho việc sử dụng functional component với React hook dựa trên những ưu điểm vượt trội của nó và có thể sử dụng kết hợp với slice của Redux Toolkit thì còn tuyệt vời hơn nữa hoặc với project đang thực hiện bạn cũng có thể chuyển dần qua sử dụng functional với các hook cho các component mới, bạn hoàn toàn có thể sử dụng cả 2 cách mà không gặp bất kỳ trở ngại nào về cả.