Professional Documents
Culture Documents
REACT REDUX
liệu quan trọng trong dự án React Native. State giống như một kho
lưu trữ dữ liệu cho các component trong ReactJS. Nó được sử dụng
để cập nhật component khi người dùng thực hiện một số hành động
như nhấp vào nút, nhập văn bản, ẩn hiện view nào đó,v.v...
Hiện tại chúng ta mới biết cách khai báo và sử dụng state trực tiếp
ngay trong từng component, thông qua sử dụng useState hook. Với
cách làm này thì không có gì sai và mọi người cũng vẫn đang làm như
vậy.
nhau, nhiều màn hình trong ứng dụng cùng dùng chung một state.
Mình lấy ví dụ điển hình đó là trường hợp bạn cần lưu trạng thái đăng
nhập của một tài khoản. Trạng thái đăng nhập sẽ ảnh hưởng tới toàn
VNTALKING.COM 133
bộ các màn hình trong ứng dụng, bạn có thể hiểu nó như một dữ liệu
Tiếp tục nhé! Vấn đề bắt đầu khó khăn hơn khi ứng dụng ngày càng
có nhiều state dạng global như vậy. Nào là trạng thái đăng nhập,
theme (dark mode, light mode), các cấu hình chung của ứng
dụng,v.v... Chúng ta cần phải có một giải pháp để quản lý các state
global này. Trong React Native, giải pháp phổ biến nhất là sử dụng
Redux.
với React. Nên nhiều người nhầm tưởng Redux là thư viện dành riêng
cho React. Nhưng thực tế thì nó có thể được sử dụng với bất kỳ
Với Redux, các state của ứng dụng được giữ trong một "store" và các
component đều có thể truy cập vào store này để lấy state.
Về cơ bản thì Redux được xây dựng có nhiều điểm chung với Flux của
Facebook.
Redux được ra đời từ việc lấy cảm hứng từ kiến trúc Flux của
Facebook. Tuy nhiên, cách tiếp cận của Redux lại hơi khác Flux một
chút. Để rõ hơn phần này, chúng ta cùng xem nguyên lý hoạt động cơ
VNTALKING.COM 134
Nguyên lý hoạt động Redux
Để sử dụng Redux dễ dàng hơn, chúng ta cần phải “thông suốt” được
• Single store: Nguyên tắc đầu tiên của Redux là tất cả các state
được chứa trong một store duy nhất, store này thường là một
Object.
này có nghĩa là Object để lưu trữ state không cho phép chỉnh
sửa, cập nhật dữ liệu trực tiếp từ bất kỳ component nào. Để cập
phải tuân theo quy trình của Redux, đó là gửi các actions và để
• Pure functions: Tất cả các functions để cập nhật hay tạo mới
state (Redux gọi các function này là reducer) phải là các pure
function. Mình hiểu đơn giản pure function là một hàm mà khi
các params đầu vào không thay đổi thì kết quả return luôn luôn
không thay đổi, dù hàm đó có thực thi bao nhiêu lần đi chăng
nữa.
Từ những nguyên lý trên, chúng ta bắt đầu tìm hiểu cụ thể trong
Redux có những thành phần gì? vai trò và nhiệm vụ của chúng như
nào.
VNTALKING.COM 135
Hình dưới đây minh họa cho toàn bộ cơ chế hoạt động của Redux:
Mình sẽ giải thích chi tiết hơn các thành phần trong hình trên:
“Store” có nhiệm vụ lưu trữ toàn bộ state của ứng dụng, nó được tạo
dưới đây:
Chúng ta chỉ nên tạo duy nhất một store để dùng chung cho toàn
“Actions” thực chất là đối tượng Javascript được gửi đi bằng phương
thức dispatch() của React Native. Những actions này bắt buộc phải có
thuộc tính type để xác định loại action được thực hiện.
VNTALKING.COM 136
Giá trị của thuộc tính type là duy nhất, tương ứng với
action đó. Bạn không nên để trùng nhau vì sau này sẽ phát
sinh nhiều lỗi rất khó chịu. Kiểu như dispatch() một action
mà ứng dụng lại cập nhật trạng thái lung tung, không đúng
ý của mình.
Trong đối tượng Action này, bạn hoàn toàn có thể gửi thêm thông tin
thông qua thuộc tính payload. Ví dụ: thông tin là các giá trị mới của
“Reducers” là pure function để cập nhật, thay đổi giá trị state được
lưu trong store. Các Reducers sẽ căn cứ vào action và payload được
Ví dụ một đoạn mã dưới đây cách Reducers cập nhật state lưu thông
VNTALKING.COM 137
// Reducer
const initialState = {
username: '',
password: ''
};
const loggeduser = (state = initialState, action) => {
switch (action.type) {
case "LOGIN":
return {
username : action.payload.username,
password : action.payload.password
};
default:
return state;
}
};
Ok, Lý thuyết về Redux cơ bản chỉ như vậy thôi, chúng ta cũng không
cần phài đào sâu quá làm gì, mình biết những cái cần thiết trước và
Phần tiếp theo, chúng ta cùng nhau thực hành một ví dụ nhỏ về cách
cài đặt, cấu hình để sử dụng Redux trong dự án React Native nhé.
Để cài đặt Redux cho dự án React Native, chúng ta cũng thực hiện
VNTALKING.COM 138
Sau khi cài đặt xong thì chúng ta tiến hành cấu hình cơ bản để Redux
hoạt động được với dự án. Bạn tải mã nguồn starter cho phần này về
Chuong9-Redux-Starter.zip
Trong ví dụ này, chúng ta sẽ tạo một ứng dụng tăng giảm biến đếm
Chương 6 - phần State. Tuy nhiên, ở chương 6, chúng ta thực hiện lưu
state trực tiếp trong component. Đến chương này, chúng ta sẽ thử
VNTALKING.COM 139
Trước hết, chúng ta dựng lại giao diện ứng dụng giống như trên đã
screens/Home.js
<TouchableOpacity onPress={handleIncreament}
style={styles.btn}>
<Text style={styles.btn_text}> Tăng điểm </Text>
</TouchableOpacity>
<TouchableOpacity
onPress={handleDecreament}
style={{ ...styles.btn, backgroundColor: '#6e3b3b'
}}>
<Text style={styles.btn_text}> Giảm điểm </Text>
</TouchableOpacity>
</View>
</View>
)
VNTALKING.COM 140
}
const styles = StyleSheet.create({
textHeader: {
fontSize: 18,
fontWeight: "bold",
color: "#FFFFFF"
},
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
flexDirection: 'column',
padding: 50,
},
title_text: {
fontSize: 40,
fontWeight: '900',
marginBottom: 55,
},
counter_text: {
fontSize: 35,
fontWeight: '900',
margin: 15,
color: '#D64545'
},
btn: {
backgroundColor: '#086972',
padding: 10,
margin: 10,
borderRadius: 10,
},
btn_text: {
fontSize: 23,
color: '#fff',
},
})
Còn file App.js sẽ cấu hình để trỏ sang màn hình Home.
VNTALKING.COM 141
App.js
Bước tiếp theo, chúng ta sẽ định nghĩa các action tương ứng với hai
“redux” dành riêng cho toàn bộ code liên quan tới redux.
Tạo file countAction.js trong thư mục redux và định nghĩa action
redux/countAction.js
Sau đó, chúng ta tạo countReducer.js (vẫn để trong thư mục redux)
VNTALKING.COM 142
redux/countReducer.js
const initialState = {
count: 0,
};
Đây là reducer dùng để cập nhật state lưu giữ trạng thái biến đếm,
với giá trị mặc định là 0, tức là mỗi lần mở ứng dụng, ứng dụng sẽ
Bước tiếp theo, chúng ta tạo một store để lưu giữ state, cụ thể là
“count” state.
redux/store.js
VNTALKING.COM 143
count: CountReducer,
});
Gần xong rồi! Sau khi các món ăn đã chuẩn bị xong hết rồi, rượu
ngon cũng đã sẵn sàng, giờ là đi mời các bạn hiền tới nhậu thôi
Đùa thôi, (viết sách nhiều khi bị tẩu hỏa nhập ma, mong bạn thông
cảm!). Bước tiếp theo là chúng ta thực hiện kết nối store vừa tạo ở
Chúng ta quay trở lại file App.js và thay đổi code một chút:
App.js
Trong đoạn code trên, mình bọc toàn bộ màn hình ứng dụng vào
trong Provider.
VNTALKING.COM 144
Như vậy là đã kết nối xong rồi đấy. Giờ là lúc sử dụng thôi. Quay lại
màn hình Home, mình sẽ chỉnh sửa code một chút để nó lưu giá trị
screens/Home.js
<TouchableOpacity onPress={handleIncreament}
style={styles.btn}>
<Text style={styles.btn_text}> Tăng điểm </Text>
</TouchableOpacity>
VNTALKING.COM 145
<TouchableOpacity
onPress={handleDecreament}
style={{ ...styles.btn, backgroundColor: '#6e3b3b'
}}>
<Text style={styles.btn_text}> Giảm điểm </Text>
</TouchableOpacity>
</View>
</View>
)
}
Ở đây, chúng ta sử dụng các hooks được cung cấp bởi thư viện react-
redux để gửi action và truy cập vào store. Cụ thể là hai hooks sau:
Các bạn chạy ứng dụng để tận hưởng thành quả nhé:
VNTALKING.COM 146
Tải mã nguồn tham khảo
Hãy thực hành chạy thử với mã nguồn đầy đủ của phần này nhé
Chuong9-Redux-Counter-Final.zip
Tổng kết
Qua tìm hiểu lý thuyết và thực hành ví dụ trên, bạn thấy Redux này
thế nào? Việc quản lý State qua redux nó có ích lợi gì không?
Có thể bạn sẽ bật ra ngay ý nghĩ kiểu: Việc để state trong store tập
trung như này chả khác gì khi vừa nhận lương tháng, vội vàng cất vào
két sắt, xong lại vội vàng mở két lấy ra để đi uống bia cả. Thực tế thì
Quan điểm cá nhân: với những trường hợp state nào mà không cần
chia sẻ cho nhiều màn hình thì đúng là không cần phải quản lý tập
trung, gây phức tạp thêm tình hình. Tuy nhiên, nếu bạn là người ngăn
nắp, thích gọn gàng thì việc quản lý tập trung state về một mối cũng
có nhiều điểm lợi thế. Đặc biệt là khoản debug ứng dụng qua React
Dev Tools.
VNTALKING.COM 147