Redux "使用"教程
来源:互联网 发布:js中window事件 编辑:程序博客网 时间:2024/05/22 03:18
如果在使用过程中遇到什么问题,欢迎加QQ群397885169
讨论。
如果觉得识兔项目可以,欢迎给个star,在稍后的日子里,识兔将会不断完善,如果有什么有意思的需求可以提出来,我可能会加在识兔里面哦!
本文的Demo
最终的运行效果
前言
本文仅写给在项目中没用使用过redux
,又急于利用redux
开发的同学们。
之前开源rn版百思不得姐的时候,写过几篇文章,有人问什么时候会出rn+redux
的文章,我也犹豫了很久,因为在开源百思的时候,没有用到跨页面传递状态。
上个月我开源了识兔(可以识别手机中或者拍摄的图片),本来打算使用mobx
来做状态管理的,但在真正使用过程中,可能是我的方法不对,我总感觉mobx
总有那么一点欠缺,深思熟虑之后,还是决定使用redux
来管理项目中的状态。
在之前学习redux
的过程中发现,网上和Github
上确实有很多开源redux
的例子,和介绍redux
的文章,但很少有从新手角度考虑的文章,绝大部分新手不一定需要知道redux
是干什么的,他们只是想尽快的在项目中使用它,而我也认为不用你咋知道原理是啥,所以我写了这篇文章,用识兔项目中的几个小案例来让新同学入了redux
的门。
ps:哪怕真的不愿意知道
redux
的原理,也需要知道redux
中基本概念和 API,比如说在项目中会经常用到的Store
、Action
、Reducer
等等。而为了知道怎么用,最简单的方式就是去看其他开源的项目,但看的越多只会让你的思路越凌乱,所以在文章中用我的写法,每个人理解的redux
都不一样,但万变不离其宗,学会一种之后可以再根据自己的需求更改。
需求
1.网络请求:redux
最简单的需求当然就是网络请求了,识兔首页,进入App的时候是需要请求一次网络的,用来验证UserToken,如果不存在就从网络获取并保存,如果存在就直接取出来。
2.跨页面修改状态:识兔的首页背景图是个大美女,我要在福利(瀑布流)页面的图片详情中,可以修改首页的背景图,之前的写法是通过通知的方式,但redux
本身就是可以跨页面传值的。
实现
逆向工程
为什么要提到逆向工程
呢?
因为本文的写法可能会与正常的数据redux
逻辑不太一样,它会反着写,会让你很快看到效果,而不是要全部把Action
、Reducer
全都写完了,才能看到完整的效果。
用到的redux库
redux,react-redux,redux-logger,redux-thunk
1. 包装入口文件
入口文件
:因为在rn
中,iOS
和安卓
平台入口是两个文件index.ios.js
和index.android.js
,为了跨平台,一般都会创建统一的入口文件。识兔项目的入口文件是app目录下的index.js文件。
index.js
import { AppRegistry,View,Text } from 'react-native';import React, { Component } from 'react';// 引入react-reduximport {Provider}from 'react-redux';// 引入store文件,下步会创建import configureStore from './store/ConfigureStore';// 调用 store 文件中的rootReducer常量中保存的方法const store = configureStore();// 项目中使用了react-navigation,推荐的做法是将初始文件写在一个文件中,// 所以App.js也可以看做是页面的初始化入口import App from './APP';export default class Root extends Component { render() { return ( // 包装App <Provider store={store}> <App /> </Provider> ); }}
2. 创建ConfigureStore
文件
store
:在上一步的时候,会发现有一个ConfigureStore
,这个就是我们俗称的store
。
ConfigureStore.js
// redux库里面提供的方法,创建store和middleware中间件import {createStore,applyMiddleware} from 'redux';// redux-thunk是用来发送异步请求的中间件,用了thunk之后,// 一般的操作是将网络请求的方法放在action中,后面会有说明import thunk from 'redux-thunk';// redux-logger打印logger的中间件,具体效果可以看下图import logger from 'redux-logger';// rootReducer下一步会创建import RootReducer from '../reducers/RootReducer';let middlewares = [];middlewares.push(logger);middlewares.push(thunk);// 通过applyMiddleware将中间件添加const createStoreWithMiddleware = applyMiddleware(...middlewares)(createStore);// 导出configureStore,里面携带着reducer,中间件,初始值export default function configureStore(initialState){ return createStoreWithMiddleware(RootReducer,initialState);}
3. 创建RootReducer
文件
reducer
:RootReducer
中放的是各个页面的Reducer
,推荐的做法是一个页面公用一个Reducer
,便于之后管理。
RootReducer.js
// Reducer是纯函数,里面不应该有过多的逻辑。import { combineReducers } from 'redux';// 这个是ShiTu页面中用到的Reducerimport ShiTuReducer from './ShiTuReducer';// 下面这个还未实现// import GankReducer from './GankReducer';// 取决于这里你加入了多少 reducerconst RootReducer = combineReducers({ ShiTuReducer,});export default RootReducer;
ShiTuReducer.js
// ActionTypes里面存放着App中可能发生的情况import * as types from '../constant/ActionTypes';// 初始化值const initialState = { imageURL: 'timg', userToken: '', webViewUrl: '', qiNiuData: null,};// 导出ShiTuReducer。export default function ShiTuReducer(state = initialState, action){ // console.log(action); // 通过switch来判断types的值,在action中实现功能 switch (action.type) { // 当type=USER_TOKEN_SUCCESS时,会将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; }}
4. 创建ActionTypes
文件
actionTypes
:在使用redux
过程中,需要给每个动作添加一个actionTypes
类型,比如说在上面,我要获取userToken
,就需要再actionTypes
中加上USER_TOKEN
,而有些时候,调用网络会有成功/失败两种状态,所以可以将这个状态更加细分USER_TOKEN_SUCCESS
/USER_TOKEN_ERRO
。
ActionTypes.js
// 用户Tokenexport const USER_TOKEN_SUCCESS = 'USER_TOKEN_SUCCESS';// 获取失败export const USER_TOKEN_ERROR = 'USER_TOKEN_ERROR';// 首页背景图片export const BACKIMAGE_URL = 'BACKIMAGE_URL';
5. 创建xxxAction
文件
xxxAction
:可能在一个页面需要用到多个action
,比如说我识兔页面中,进入app的时候需要调用获取userToken的action,点击查找按钮的时候需要调用获取图片信息的action。每个页面是可以有多个action的,只需要在页面中引入就好
ShiTuUserToken.js
// 获取actionType中的全部状态,需要哪个就用哪个import * as types from '../constant/ActionTypes';// 网络请求的网址和网络请求的方法import Config from '../common/Config';import Request from '../common/Request';import { AsyncStorage } from 'react-native';// 存储信息的KEYlet KEY = 'USERTOKEN';// 这个方法是请求网络,获取Token的方法// 识兔中调用这个方法之后,需要判断是否存在userToken,不存在请求网络并保存,存在直接调用返回export function userToken() { return dispatch => { return Request.get(Config.api.getUserToken,(data)=>{ AsyncStorage.getItem(KEY,(Error,result)=>{ if (result === null){ Request.get(Config.api.getUserToken,(data)=>{ // console.log(data); if (data && data.success){ let token = data.token; AsyncStorage.setItem(KEY,token,(error)=>{ if (error){ console.log('存储失败' + error); }else { console.log('存储成功'); // dispatch发送数据到Reducer里面 dispatch(getUserToken(token)); } }) } },(error)=>{ console.log(error); }) }else { console.log('获取成功' + result); dispatch(getUserToken(result)); } }); },(error)=>{ console.log(error); dispatch({type: types.USER_TOKEN_ERROR, error: error}); }); }};// 如果()括号里面的参数`userToken`和Reducer里面的初始参数一样,就可以不用键:值的写法,直接返回就好。export function getUserToken(userToken) { return { // type是必要参数,通过type值判断 type: types.USER_TOKEN_SUCCESS, userToken }}
6. connect
连接页面和Reducer
,完成需求1
connect
:如果完成了上面的步骤,恭喜你,还差最后一步就可以看到运行的效果了,那就是在需要的页面connect
。因为ShiTu.js
中代码过多,所以只在文章中放重要的部分,如果想要查看全部,可以运行项目或者直接查看ShiTu.js
ShiTu.js
// 引入需要用到的方法···// 引入connect和bindActionCreatorsimport { connect } from 'react-redux';import { bindActionCreators } from 'redux';// 引入获得userToken的action方法import { userToken } from '../../actions/ShiTuUserToken';···// 导出ShiTu页面并连接Reducer···// connect 连接 Recucer ,我ShiTu.js的Reducer叫ShiTuReducer,// userToken等方法是我在action里面创建的,所以调用的也就是action方法export default connect((state) => { const { ShiTuReducer } = state; return { ShiTuReducer };},{ userToken })(ShiTu)···// 使用componentDidMount(){ console.log('componentDidMount'); // 使用userToken方法。 this.props.userToken(); } render() { console.log('render'); // 掉用过上面的方法后就可以通过打印`ShiTuReducer`获得需要的数据 console.log(this.props.ShiTuReducer);}
完成上面的6步,就可以在现有的项目中使用redux
开发了。在第6步中我们只是完成了需求1,接下来就要利用redux
实现跨页面更改状态了。
1. 寻找需求
并不是每个App都需要用到跨页面更改状态的,但在识兔中,我心中的想法是,识兔项目中多数的页面布局都可以由用户自定义,所以我选择了redux
,如果不需要用到跨页面更改状态,使用state管理也是没有问题的。
需求2的操作流程是,在福利的图片详情页WelfarePicture.js
中长按图片弹出actionSheet,点击设为主屏幕
就可以修改首页的背景图片了。
2. 实现
实现逻辑和获取userToken基本一样,唯一的区别就是,点击按钮的时候,需要通过dispatch传递图片的url地址到Reducer中。
WelfarePicture
// 因为···import { connect } from 'react-redux';import { bindActionCreators } from 'redux';import { backImage,getBackImage } from '../../actions/ShiTuBackImage';······export default connect((state) => { const { ShiTuReducer } = state; return { ShiTuReducer };},{ backImage,getBackImage})(WelfarePicture)···// 下面的方法就是点击actionSheet的方法···handlePress(url,i) { let SHITUIMAGEKEY = 'SHITUIMAGEKEY'; if(i===2){ AsyncStorage.setItem(SHITUIMAGEKEY,url,(error)=>{ if (error){ console.log('存储失败' + error); }else { console.log('存储成功'); // 通过getBackImage方法将图片的url发给Reducer,Reducer中就会相应的更新页面 this.props.getBackImage(url); } }) } }···
总结
在文章中真的没有多说redux
原理,如果有想了解的同学可以参考阮一峰老师的几篇文章,讲的清晰透彻。
本文只是我对于实现redux
的一点看法,可能并不适用于你的项目,如果在使用过程中遇到什么问题,欢迎加QQ群397885169
讨论。
如果认为我的文章不错,欢迎打赏,关注,喜欢。
如果感觉我的文章有问题,欢迎在评论区提出,我会修改。
- Redux "使用"教程
- Redux "使用"教程
- React Native 之 Redux使用教程
- React+Redux系列教程
- Redux 简明教程
- Redux 简明教程
- Redux 进阶教程
- react+redux教程
- Redux 莞式教程
- Redux 进阶教程
- Redux 简明教程
- Redux-form系列教程
- React+Redux系列教程
- 使用Redux DevTools浏览器插件调试redux
- 使用Redux DevTools浏览器插件调试redux
- Redux状态管理5 使用react-redux
- react-native-redux 简易教程
- React-redux使用
- codevs 2021 中庸之道
- HDU 5328 Problem Killer
- YUM学习
- 【Spring】在WEB应用中使用Spring
- html总结
- Redux "使用"教程
- 南阳OJ 949题 哈利波特
- android login
- JZ2440存储管理器学习
- ie7下overflow:hidden不起作用
- codeforces 822A(I'm bored with life) Java
- POJ 1840 Eqs 笔记
- 1321: 光辉女郎之终极闪光
- algorithm下的常用函数