Hướng dẫn cách sử dụng Redux để quản lý State trên ứng dụng
20/12/2021 11:53
Đôi khi chúng ta sẽ cần thiết lập trạng thái hoặc xử lý logic đúng cách, nhưng không thể sử dụng được các trạng thái. Hoặc có thể làm cho mọi thứ hoạt động, nhưng làm lộn xộn codebase trong quá trình này, khiến nó khó đọc và mở rộng hơn. Việc sử dụng một nguồn đơn duy nhất cho phép Redux chiếm ưu thế hơn so với API ngữ cảnh truyền thống. Vậy hãy cùng xem cách chúng ta có thể sử dụng Redux tốt nhất để quản lý trạng thái trên toàn ứng dụng bằng cách viết mã sạch hơn và tối ưu hơn không ngay trong bài viết này!
Cách tạo Redux Store mà không cần Redux Toolkit
Với các ứng ứng thương mại điện tử, bạn sẽ muons theo dõi và phát nhiều trạng thái trên các thành phần khác nhau. Theo nguyên tắc chung, bạn có thể vạch ra ý tưởng sơ bộ trước khi bước vào quá trình làm việc. Khi làm ứng dụng thương mại điện tử, các trạng thái quan trọng nên được cân nhắc là:
- Authentication
- Cart tracking
- Watchlist
Bạn có thể chia state handling logic và state thành các module khác nhau, sau đó kết hợp chúng vào một cửa hàng đơn nhất!
Để làm được điều này, bạn có thể sử dụng Redux Toolkit. Redux Toolkit là một thư viện thứ ba như Redux, tạo và duy trì bởi team Redux.
Bạn có thể cân nhắc tạo sao Redux tạo Redux Toolkit ngay từ đầu, lý do là:
- Redux Toolkit là cách chuẩn nhất để viết Redux. Ban đấu nó được tạo ra để giúp giải quyết ba mối quan tâm phổ biến về Redux như: Định cấu hình của Redux Store quá phức tạp. Phải thêm nhiều Redux Package để làm những điều hữu ích. Redux yêu cầu nhiều mã soạn sẵn.
Cách cài đặt Redux Toolkit
Bạn có thể cài đặt Bộ công cụ Redux bằng npmhoặc yarnnhư sau:
- npm install @reduxjs/toolkit
- yard add @reduxjs/toolkit
Cách sử dụng Redux Toolkit
Điểm dừng đầu tiên khi tạo cửa hàng Redux là thiết lập xử lý trạng thái.
Thay vì sử dụng bộ giảm, chúng tôi sẽ sử dụng bộ createSlicecông cụ Redux cung cấp.
createSlice chấp nhận 3 đối số bắt buộc, đó là:
- name : tên của lát cắt
- InitialState : trạng thái ban đầu của lát cắt (Đây giống như trạng thái ban đầu của bộ giảm tốc)
- reducers: hàm ảnh hưởng đến states
Tóm lại, slice là một gói mô-đun hóa các trạng thái và hành động của chúng.
Hãy bắt đầu bằng cách tạo một lát để xác thực và các hành động liên quan của nó:
const authSlice = createSlice({
name: 'Auth', // Could name it anything
initialState: {
isLoggedIn: false,
},
reducers: {
login: (state) => {
state.isLoggedIn = true
},
logout: (state) => {
state.isLoggedIn = false
},
},
})
Như bạn có thể thấy, phần trên dành riêng cho xác thực người dùng. initialStatelà một đối tượng có chứa các giá trị trạng thái ban đầu khác nhau và các trạng thái mà bộ giảm tốc cần thực hiện. Các hàm trong bộ giảm tốc giống như bộ giảm tốc thông thường chấp nhận trạng thái và hành động làm đối số.
Một điểm đáng chú ý trong đoạn mã trên là cách chúng tôi đang xử lý việc cập nhật trạng thái state.isLoggedIn = true. Đây rõ ràng là đột biến trạng thái, vi phạm tính chất bất di bất dịch.
Cách kết hợp slice vào một store duy nhất
Một Redux store chỉ có một reducers, vì vậy điều quan trọng là phải kết hợp tất cả các bộ phận và bộ giảm tốc của chúng thành một bộ giảm tốc duy nhất mà không làm mất đi tính đặc trưng và chức năng của nó.
Để thực hiện điều này, chúng tôi sẽ sử dụng configureStoređể createStore.
configureStore tương tự như createStore, nhưng nó có thể hợp nhất các bộ giảm của nhiều slice thành một bộ giảm tốc duy nhất.
Nó có một đối tượng reducer chấp nhận một hoặc nhiều slice, như thế này:
import { authSlice } from './auth-slice'
import { cartSlice } from './cart-slice'
import { wathclistSlice } from './watchlist-slice'
const store = configureStore({
reducer: {
authSliceReducer: authSlice.reducer,
cartSliceReducer: cartSlice.reducer,
watchlistSliceReducer: watchlist.reducer,
},
})
export defualt store
Cách sử dụng Redux State trong components
Bây giờ chúng ta đã có sẵn Redux store, chúng ta có thể sử dụng và gửi các hành động từ các thành phần bằng cách sử dụng useSelectorvà useDispatchhook.
Đây là một ví dụ đơn giản:
import { useDispatch, useSelector } from 'react-redux'
import { cartActions } from '...'
export default function Cart(props) {
const dispatch = useDispatch()
const selector = useSelector((state) => state.watchlistSliceReducer) // Since the store has multiple reducers, we need to drill into the appropriate slice state.
const addToCartHandler = () => {
const dummyitem = {
id: Math.random(),
name: `Dummy Item ${Math.random()}`,
price: 20 * Math.random(),
}
dispatch(cartActions.addItem(cartItem.dummyitem))
}
const removeFromCartHandler = (id) => {
dispatch(cartActions.removeItem(id)) //Passing id as an argument to the reducer function.
}
return (
<div>
{selector.cart.length &&
selector.cart.map((item) => {
return (
<div>
<p>Name: {item.name}</p>
<p>Price: {item.price}</p>
<p>Quantity: {item.qty}</p>
<button onClick={removeFromCartHandler}>Remove item</button>
</div>
)
})}
<h3>Total cart value:{selector.cart.total}</h3>
<button onClick={addToCartHandler}>Add dummy item</button>
</div>
)
}