上節(jié)我們已經(jīng)完成對(duì)redux和navigation的集成了
下面我們來說明一下redux使用步驟
首先我們來看一張圖

圖片1.png
這里我們了解一下三個(gè)概念 store、action、reducer,store存儲(chǔ)數(shù)據(jù),action,請(qǐng)求狀態(tài)改變動(dòng)作,reducer就是改變狀態(tài)
redux整個(gè)流程原理可以這樣來描述,用戶通過可視化界面View觸發(fā)一個(gè)請(qǐng)求動(dòng)作,在程序內(nèi)部觸發(fā)一個(gè)Action,Action完成數(shù)據(jù)請(qǐng)求和變化工作后,通過reducer來更新state,并寫入store中,整個(gè)流程操作完畢。
下面我們來完成一個(gè)實(shí)例,一個(gè)簡(jiǎn)單獲取token的過程
1.定義獲取token的Action
let KEY = 'USERTOKEN';
export function userToken() {
return dispatch => {
return AsyncStorage.getItem(KEY,(Error,result)=>{
if (result === null){
let data = JSON.parse('{"success":true,"token":"e143e928-032c-47ea-a571-f49bcaf83842"}');
if (data && data.success){
let token = data.token;
AsyncStorage.setItem(KEY,token,(error)=>{
if (error){
console.log('存儲(chǔ)失敗' + error);
// Alert.alert('獲取失敗,請(qǐng)稍后重試');
}else {
console.log('存儲(chǔ)成功');
dispatch(getUserToken(token));
}
})
}
}else {
console.log('獲取成功' + result);
// TOKEN = '0ddc64eb-48e3-4d4c-a83c-a61caa2450d4';
dispatch(getUserToken(result));
}
});
}
};
export function getUserToken(userToken) {
return {
type: types.USER_TOKEN_SUCCESS,
userToken
}
}
這里非常簡(jiǎn)單就是判斷內(nèi)存里面有沒有存儲(chǔ)“userToken”沒有就寫入 ,然后返回token操作。
有了action,就應(yīng)該有有保存action返回的結(jié)果,接下來我們來定義一個(gè)reducer
// Reducer是純函數(shù),里面不應(yīng)該有過多的邏輯。
import { combineReducers } from 'redux';
// 這個(gè)是ShiTu頁面中用到的Reducer
import ShiTuReducer from './ShiTuReducer';
import StackReducer from './StackReducer';
const RootReducer = combineReducers({
ShiTuReducer,
StackReducer
});
export default RootReducer;
// ActionTypes里面存放著App中可能發(fā)生的情況
import * as types from '../constant/ActionTypes';
// 初始化值
const initialState = {
imageURL: 'timg',
userToken: '',
webViewUrl: '',
qiNiuData: null,
};
// 導(dǎo)出ShiTuReducer。
export default function ShiTuReducer(state = initialState, action){
// console.log(action);
// 通過switch來判斷types的值,在action中實(shí)現(xiàn)功能
switch (action.type) {
// 當(dāng)type=USER_TOKEN_SUCCESS時(shí),會(huì)將action中的值,
// 賦給userToken,在ShiTu.js中就能拿到userToken的值。
case types.USER_TOKEN_SUCCESS:
// console.log(action);
return Object.assign({}, state, {
...state,
userToken: action.userToken,
});
case types.QINIU_UPLOAD_TOKEN:
// console.log(action);
return Object.assign({}, state, {
qiNiuData:action.qiNiuData,
});
case types.WEBVIEW_URL:
return Object.assign({}, state ,{
...state,
webViewUrl:action.webViewUrl,
});
case types.BACKIMAGE_URL:
return Object.assign({}, state ,{
imageURL:action.imageURL,
});
default:
return state;
}
}
import { MyApp } from '../App';
export default function StackReducer(state , action) {
let nextState = MyApp.router.getStateForAction(action, state);
return nextState || state;
}
以上三段代碼解釋一下,我們知道Action有好多個(gè),那么觸發(fā)保存Action結(jié)果的reducer也必須有多個(gè),那么這里rootReducer相當(dāng)于一個(gè)合成器一樣,把所有reducer合成在一起,而其他reducer就可以各自寫入一個(gè)獨(dú)立的文件中,不相互影響
最后一步,在Main2中如何使用呢?
export default connect((state) => {
const { ShiTuReducer ,StackReducer } = state;
return {
ShiTuReducer,
StackReducer
};
},{ userToken })(Main2);
class Main2 extends Component {
constructor(props){
super(props);
this.state = {
userName:'linjian',
userToken:'',
}
this.resetActions = this.resetActions.bind(this);
this.goBack = this.goBack.bind(this)
}
componentDidMount(){
// 使用userToken方法。
this.props.userToken();
}
componentWillReceiveProps(nextProps){
const { userToken} = nextProps.ShiTuReducer;
this.setState({userToken:userToken});
}
resetActions(){
//這個(gè)方法是重置了整個(gè)路由棧信息,那我們要在actions中重新定義路由棧,下面的的index參數(shù)代表新路由棧默認(rèn)顯示的頁面
const resetAction = NavigationActions.reset({
index: 1,
actions: [
NavigationActions.navigate({ routeName: 'ReactNavigation'}),
NavigationActions.navigate({ routeName: 'profile'})
]
})
this.props.navigation.dispatch(resetAction)
}
goBack(){
// debugger;
let routes = this.props.StackReducer.routes;
routes.forEach(function(item) {
if(item.routeName === 'Main2'){
const { goBack } = this.props.navigation;
goBack(item.key);
}
}, this);
}
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
Welcome to Main22222!
</Text>
<Text style={styles.instructions}>
The user toke is {this.state.userToken}
</Text>
<Text style={styles.instructions}>
Double tap R on your keyboard to reload,{'\n'}
Shake or press menu button for dev menu
</Text>
<Text style={styles.instructions}>
userName:{this.state.userName}
</Text>
<TouchableOpacity onPress={()=>{this.resetActions()}}>
<Text>跳轉(zhuǎn)到ProfileScreen并替換掉main2</Text>
</TouchableOpacity>
<TouchableOpacity onPress={()=>{nav.push("Main3")}}>
<Text>跳轉(zhuǎn)到main3</Text>
</TouchableOpacity>
</View>
);
}
}
這樣usertoken就能顯示了