React 实践项目 (三)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架。而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战!
上回说到使用Redux进行状态管理,这次我们使用Redux-saga 管理 Redux 应用异步操作
React 实践项目 (一)
React 实践项目 (二)
React 实践项目 (三)
- 首先我们来看看登陆的 Reducer
export const auth = (state = initialState, action = {}) => {
switch (action.type) {
case LOGIN_USER:
return state.merge({
'user': action.data,
'error': null,
'token': null,
});
case LOGIN_USER_SUCCESS:
return state.merge({
'token': action.data,
'error': null
});
case LOGIN_USER_FAILURE:
return state.merge({
'token': null,
'error': action.data
});
default:
return state
}
};
Sagas 监听发起的 action,然后决定基于这个 action 来做什么:是发起一个异步调用(比如一个 Ajax 请求),还是发起其他的 action 到 Store,甚至是调用其他的 Sagas。
具体到这个登陆功能就是我们在登陆弹窗点击登陆时会发出一个 LOGIN_USER action,Sagas 监听到 LOGIN_USER action,发起一个 Ajax 请求到后台,根据结果决定发起 LOGIN_USER_SUCCESSaction 还是LOGIN_USER_FAILUREaction
接下来,我们来实现这个流程
创建 Saga middleware 连接至 Redux store
在 package.json 中添加 redux-saga 依赖
"redux-saga": "^0.15.4"
修改 src/redux/store/store.js
/**
* Created by Yuicon on 2017/6/27.
*/
import {createStore, applyMiddleware } from 'redux';
import createSagaMiddleware from 'redux-saga'
import reducer from '../reducer/reducer';
import rootSaga from '../sagas/sagas';
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
reducer,
applyMiddleware(sagaMiddleware)
);
sagaMiddleware.run(rootSaga);
export default store;
Redux-saga 使用 Generator函数实现
监听 action
创建 src/redux/sagas/sagas.js
/**
* Created by Yuicon on 2017/6/28.
*/
import { takeLatest } from 'redux-saga/effects';
import {registerUserAsync, loginUserAsync} from './users';
import {REGISTER_USER, LOGIN_USER} from '../action/users';
export default function* rootSaga() {
yield [
takeLatest(REGISTER_USER, registerUserAsync),
takeLatest(LOGIN_USER, loginUserAsync)
];
}
我们可以看到在 rootSaga 中监听了两个 action 登陆和注册 。
在上面的例子中,takeLatest 只允许执行一个 loginUserAsync 任务。并且这个任务是最后被启动的那个。 如果之前已经有一个任务在执行,那之前的这个任务会自动被取消。
如果我们允许多个 loginUserAsync 实例同时启动。在某个特定时刻,我们可以启动一个新 loginUserAsync 任务, 尽管之前还有一个或多个 loginUserAsync 尚未结束。我们可以使用 takeEvery 辅助函数。
发起一个 Ajax 请求
获取 Store state 上的数据
selectors.js
/**
* Created by Yuicon on 2017/6/28.
*/
export const getAuth = state => state.auth;
- api
api.js
/**
* Created by Yuicon on 2017/7/4.
* https://github.com/Yuicon
*/
/**
* 这是我自己的后台服务器,用 Java 实现
* 项目地址:https://github.com/DigAg/digag-server
* 文档:http://139.224.135.86:8080/swagger-ui.html#/
*/
const getURL = (url) => `http://139.224.135.86:8080/${url}`;
export const login = (user) => {
return fetch(getURL("auth/login"), {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(user)
}).then(response => response.json())
.then(json => {
return json;
})
.catch(ex => console.log('parsing failed', ex));
};
- 创建 src/redux/sagas/users.js
/**
* Created by Yuicon on 2017/6/30.
*/
import {select, put, call} from 'redux-saga/effects';
import {getAuth, getUsers} from './selectors';
import {loginSuccessAction, loginFailureAction, registerSuccessAction, registerFailureAction} from '../action/users';
import {login, register} from './api';
import 'whatwg-fetch';
export function* loginUserAsync() {
// 获取Store state 上的数据
const auth = yield select(getAuth);
const user = auth.get('user');
// 发起 ajax 请求
const json = yield call(login.bind(this, user), 'login');
if (json.success) {
localStorage.setItem('token', json.data);
// 发起 loginSuccessAction
yield put(loginSuccessAction(json.data));
} else {
// 发起 loginFailureAction
yield put(loginFailureAction(json.error));
}
}
select(selector, ...args) 用于获取Store state 上的数据put(action) 发起一个 action 到 Storecall(fn, ...args) 调用 fn 函数并以 args 为参数,如果结果是一个 Promise,middleware 会暂停直到这个 Promise 被 resolve,resolve 后 Generator 会继续执行。 或者直到 Promise 被 reject 了,如果是这种情况,将在 Generator 中抛出一个错误。
Redux-saga 详细api文档
结语
我在工作时用的是 Redux-Thunk, Redux-Thunk 相对来说更容易实现和维护。但是对于复杂的操作,尤其是面对复杂异步操作时,Redux-saga 更有优势。到此我们完成了一个 Redux-saga 的入门教程,Redux-saga 还有很多奇妙的地方,大家可以自行探索。
完整项目代码地址:https://github.com/DigAg/digag-pc-react
React 实践项目 (三)的更多相关文章
- React 实践项目 (五)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一 ...
- React 实践项目 (二)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! React 实践项目 (一 ...
- android 实践项目三
android 实践项目三 本周我主要完成的任务是将代码进行整合,然后实现百度地图的定位与搜索功能.在这次实现的 图形界面如下: 在本周的工作中主要的实现出来定位与收索的功能,在地图中能实现了定位,显 ...
- React 实践项目 (一)
React在Github上已经有接近70000的 star 数了,是目前最热门的前端框架.而我学习React也有一段时间了,现在就开始用 React+Redux 进行实战! 项目代码地址:https: ...
- python实践项目三:将列表添加到字典
1.创建一个字典,其中键是字符串,描述一个物品,值是一个整型值,说明有多少该物品.例如,字典值{'rope': 1, 'torch': 6, 'gold coin': 42, 'dagger': 1, ...
- 总结 React 组件的三种写法 及最佳实践 [涨经验]
React 专注于 view 层,组件化则是 React 的基础,也是其核心理念之一,一个完整的应用将由一个个独立的组件拼装而成. 截至目前 React 已经更新到 v15.4.2,由于 ES6 的普 ...
- Immutable.js 以及在 react+redux 项目中的实践
来自一位美团大牛的分享,相信可以帮助到你. 原文链接:https://juejin.im/post/5948985ea0bb9f006bed7472?utm_source=tuicool&ut ...
- 总结 React 组件的三种写法 及最佳实践
React 专注于 view 层,组件化则是 React 的基础,也是其核心理念之一,一个完整的应用将由一个个独立的组件拼装而成. 截至目前 React 已经更新到 v15.4.2,由于 ES6 的普 ...
- Expo大作战(三)--针对已经开发过react native项目开发人员有针对性的介绍了expo,expo的局限性,开发时项目选型注意点等
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...
随机推荐
- How-to go parallel in R – basics + tips(转)
Today is a good day to start parallelizing your code. I’ve been using the parallel package since its ...
- 初码-Azure系列-记一次MySQL数据库向Azure的迁移
初码Azure系列文章目录 还在继续给客户迁移不同的系统到Azure,这一次是一个系统的MySQL数据库要迁移,将迁移过程记录一下 原系统环境 数据库版本:MySQL Community Editio ...
- 建造者模式—设计角度重温DNF中的角色
应用场景 假设现在我们要设计DNF中的人物角色(鬼剑士.神枪手.魔法师.圣骑士.格斗家).然而,利用面对对象的思想,必须先从实体入手,每一个角色都包含各种装备.武器.配饰,这些就当做要建造的零件,然后 ...
- 刨根究底字符编码之十——Unicode字符集的字符编码方式CEF
Unicode字符集的字符编码方式CEF 一.字符编码方式CEF的选择 1. 由于Unicode字符集非常大,有些字符的编号(码点值)需要两个或两个以上字节来表示,而要对这样的编号进行编码,也必须使用 ...
- Android学习笔记View的工作原理
自定义View,也可以称为自定义控件,通过自定义View可以使得控件实现各种定制的效果. 实现自定义View,需要掌握View的底层工作原理,比如View的测量过程.布局流程以及绘制流程,除此之外,还 ...
- Python教程(1.1)——配置Python环境
在正式开始学习Python之前我们需要先配置好Python环境. Python Python可以从Python官方网站上,选择适合你的操作系统的版本下载.下载完之后,运行下载的可执行文件进行安装. 这 ...
- 一天搞定CSS: 标签样式初始化(CSS reset)及淘宝样式初始化代码--09
样式初始化:是指对HTML中某些标签的默认样式进行清除 样式初始化目的: 不同浏览器的默认样式不一样,若不清理,会导致相同的代码在浏览器中解析结果不一样,为了避免这种情况,所以需要进行样式初始化. 代 ...
- ssh框架整合之登录以及增删改查
1.首先阐述一下我用得开发工具,myeclipse2017+oracle,所以我的基本配置步骤可能不一样,下面我用几张图来详解我的开发步骤. ---1先配置structs (Target 选择apac ...
- asp.net core教程 (二)
Asp.net Core环境设置 Asp.net Core环境设置 安装Microsoft Visual Studio 2015 Asp.Net Core是Asp.Net的一个重大的重新设计. 这个话 ...
- Asp.Net页面传值的方法简单总结【原创】
1.QueryString 当页面上form按照get的方式向页面发送请求数据的时候,web server会将请求数据放入 一个QEURY_STRING的环境变量中,然后通过QeueryString方 ...