一直想将项目中使用的redux,写成一篇博客,但是又碍于对Redux的掌握能力有限,只能在项目完结的时候,稍稍整理一下redux在项目中全局获取 用户的信息,从用户登录,到修改用户信息,和退出登录全局使用Redux进行保存用户信息,修改用户信息,清空用户信息,一套小小的入门代码。
项目中redux基于react-navigation,可做到:
- 某个组件的状态,需要全局共享
- 某个状态需要在任何地方都可以拿到
- 一个组件需要改变全局状态
- 一个组件需要改变另一个组件的状态
由于项目篇幅涉及的可能会比较多,简单的一些操作,这里不做教程
1、我们要npm一下redux的相关组件
redux、react-redux 、redux-actions、redux-thunk
2、当然不能少了 react-navigation
1、项目中iOS和android,我们注册导出的根组件为Root
import {
AppRegistry,
} from 'react-native';
import Root from './shop/Root';
AppRegistry.registerComponent('ReactNative', () => Root);
2、在Root.js中
import {AppStack} from './Router' // 路由栈(使用react-navigation封装出来的路由栈)
import {Provider} from 'react-redux';
import configureStore from './redux/Store'
const store = configureStore({});
export default class Root extends Component {
render() {
return (
<Provider store={store}>
<AppStack />
</Provider>
);
}
}
3、此时我们创建一个redux文件夹,里面包含Reducer,Action,Store
Store 就是保存数据的地方,你可以把它看成一个容器。整个应用只能有一个 Store。
Action 是一个对象
Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。
文件夹如下图:
4、我们先创建一个ActionTypeConf.js
// 用户信息
export const USER_INFO_GET_LOCAL = 'USER_INFO_GET_LOCAL'; // 获取本地用户信息
export const EDIT_USER = 'EDIT_USER'; // 编辑用户信息
export const USER_CLEAR = 'USER_CLEAR'; // 清空用户信息
5、创建User.js
import * as types from "../ActionTypeConf";
const initialState = {
user: {},
token:null
};
export default (state = initialState, action) => {
switch (action.type) {
case types.USER_INFO_GET_LOCAL: // 获取本地的个人信息
return Object.assign({}, state, {
user: action.user,
token: action.token
});
case types.EDIT_USER: // 编辑个人信息
let tempObj = {};
Object.assign(tempObj, state, {
user: action.user,
});
return tempObj
case types.USER_CLEAR: // 清除个人信息
return initialState;
default:
return state;
}
6、在reduxcers中创建index.js文件,导出相应的user
import { combineReducers } from "redux";
import user from "./User";
//全局状态树根节点key定义
const rootReducer = combineReducers({
user,
});
export default rootReducer;
7、在action.js中创建UserAction.js文件
import * as types from '../ActionTypeConf';
export function loadUserInfo() { // 网络请求用户信息
return dispatch => {
Api.getLocalUserInfo().then((user) => {
Api.getLocalToken().then((token) => {
if (user && token) {
Config.LoginToken=token;
dispatch({
type: types.USER_INFO_GET_LOCAL,
user, token
})
}
}).catch((err)=>{});
}).catch((err)=>{});
};
}
export function cleanUserState() { // 清除个人信息
return dispatch=> {
Api.clearLocalUserInfo().then((data) => {
dispatch({
type: types.USER_CLEAR
})
}).catch((err) =>{})
}
}
export function editUser(oldUser, param, callBack) { // 编辑个人信息
return dispatch=> {
Api.modifyUserInfo(param).then((data) => {
let user = {};
Object.assign(user, oldUser, param);
Api.setLocalUserInfo(user).then((data) => {
dispatch({
type: types.EDIT_USER,
user
})
}).catch((err)=>{})
callBack && callBack();
}).catch((err) =>{})
}
}
8、新建Store.js
import {DeviceEventEmitter} from 'react-native';
import {createStore, applyMiddleware} from 'redux';
import thunk from 'redux-thunk';
import rootReducer from './reducers/index';
export default function configureStore(initialState) {
const store = createStore(
rootReducer,
initialState,
applyMiddleware(thunk), //applyMiddleware方法中传入需要使用的中间件
);
store.subscribe(() => {
DeviceEventEmitter.emit(Config.EVENT_GLOBAL_STATE_CHANGE, {})
});
global.AppReduxStore=store;
return store;
}
9、登录, 模块导出需要绑定组件
import * as UserAction from '../../redux/actions/UserAction';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
class UserLogin extends React.Component { // 这里不能使用export导出
// 登录
Api.userLogin({userCode: this.state.phoneText, userPassword: this.state.passwordText}).then((data) => {
this.props.userAction.loadUserInfo(); // 登录成功后加载action数据
// this.dispatch(resetAction);
this.goBack();
}).catch(e => {
});
}
//绑定状态,state 变成this.props
function mapStateToProps(state, ownProps) {
return {
getUser: state.user.user
};
}
//绑定actions
function mapDispatchToProps(dispatch) {
return {
userAction: bindActionCreators(UserAction, dispatch),
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(UserLogin)
10、api中用户登录,保存本地用户信息,清除本地用户数据,获取本地用户信息等相应接口处理
/**
* 保存本地用户信息
*/
static saveLocalUserInfo(user) {
return StorageUtil.saveJsonObject(KEY_LOCAL_USER_INFO, user);
}
/**
* 获取本地用户信息
*/
static getLocalUserInfo() {
return StorageUtil.getJsonObject(KEY_LOCAL_USER_INFO).then(data => {
return data;
});
}
/**
* 清除本地用户信息
*/
static async clearLocalUserInfo() {
await StorageUtil.remove(KEY_LOCAL_USER_INFO);
return true
}
/**
* 登陆
* @param params
* @returns {Promise}null
*/
static userLogin(params = {userCode: '', verifyCode: ''}) {
return callApi(url, params, {
method: NetUtil.POST, showLoading: true, resultCallBack: async (result) => {
if (result && result.data && result.data.auth) {
await this.userObtainInfo(); //登录完成获取用户信息
}
return true;
}
});
}
/**
* 网络请求用户信息
*/
static userObtainInfo() {
let url = Config.HOST_TRADE_CORE + '/api/v1/yundt/trade/member/detail/get';
return callApi(url, {}, {
method: NetUtil.GET, showLoading: true, resultCallBack: async(result) => {
if (result && result.data) {
this.saveLocalUserInfo(result.data)
}
return true;
}
});
}
11、在个人中心页面获取绑定的redux保存到本地的值
import * as UserAction from '../../redux/actions/UserAction';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
class Mine extends React.Component { // 这里不能使用export导出
componentWillMount() {
Console.log(this.props.getUser) //打印本地存储的网络请求下来的数据
}
render() {
const {realName, mobile, menberId} = this.props.getUser;
return (
<View style={styles.container}>
<Text>{realName}</Text>
</View>
);
}
}
//绑定状态,state 变成this.props
function mapStateToProps(state, ownProps) {
return {
getUser: state.user.user
};
}
//绑定actions
function mapDispatchToProps(dispatch) {
return {
userAction: bindActionCreators(UserAction, dispatch),
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Mine)
12、编辑用户信息
// 因为编辑个人信息可能包含用户名,手机号码之类的,所以这里在redux统一处理,只要外界把要修改的字段传入。
this.props.userAction.editUser(this.props.getUser, {realName: this.state.nameText}, () => {
Toast.show('修改成功', { // 提示修改成功
duration: Toast.durations.SHORT,
position: Toast.positions.BOTTOM,
shadow: true,
animation: true,
hideOnPress: true,
delay: 0,
backgroundColor: '#000000'
})
,this.goBack()})
13、退出登录
this.props.userAction.cleanUserState();