react-redux: async promise
1、the simple sample
action: 事实上,只是返回个一个至少包含type的对象{ },用于reducer接收。
import {RECEIVE_DATA} from "constant/ActionType";
import MessageService from "service/demo-service/MessageService";
const _messageService = new MessageService();
function receiveData(data) {
return {
type: RECEIVE_DATA,
list: data
}
}
export function fetchData() {
return (dispatch) => {
_messageService.getMessage().then(res => {
dispatch(receiveData(res.data))
})
}
}
reducer:对应某个actionType有相应的数据返回
import {RECEIVE_DATA} from "constant/ActionType";
const initialState = {
message: []
};
const MessageReducer = function (state = initialState, action) {
switch (action.type) {
case RECEIVE_DATA:
return {message: action.list};
default:
return state;
}
};
export default MessageReducer;
use:
const mapStateToProps = state => {
return {
messageList: state.MessageReducer.message
}
};
const mapDispatchToProps = {
fetchMessageList: fetchData
};
componentDidMount() {
this.props.fetchMessageList();
}
2、Async Action Helpers
// status constants
export const REQUEST = 'request';
export const SUCCESS = 'success';
export const FAILURE = 'failure'; export const createAsyncAction = (type, promiseCreator) => {
return () => (dispatch, getState) => { dispatch({ type, readyState: REQUEST }); const promise = promiseCreator();
return promise.then(
data => {
dispatch({ type, readyState: SUCCESS, data });
},
error => {
dispatch({ type, readyState: FAILURE, error });
}
);
};
};
use:
function latestPostsRequest() {
return fetch(`https://www.reddit.com/latest.json`)
.then(
response => response.json(),
error => console.log('An error occured.', error)
)
}
const FETCH_LATEST_POSTS = 'Actions/Posts/FetchLatest';
export const fetchLatestPosts = createAsyncAction(FETCH_LATEST_POSTS, latestPostsRequest);
result:
import { fetchLatestPosts } from '../actions/posts';
// in some component...
dispatch(fetchLatestPosts);
// immediately:
// { type: 'Actions/Posts/FetchLatest', readyState: 'request' }
// after success:
// {
// type: 'Actions/Posts/FetchLatest',
// readyState: 'success',
// data: (some blob of json data from the api)
// }
3、More sophisticated actions: Args and Thunks
export const createAsyncAction = (type, promiseCreator) => {
// get hash of args to pass through to promise creator
return (args = {}) => (dispatch, getState) => {
dispatch({ args, type, readyState: REQUEST });
// pass args through
let promise = promiseCreator(args);
// handle thunk-style promises
if (typeof promise === 'function') {
promise = promise(dispatch, getState);
}
return promise.then(
data => {
dispatch({ args, type, readyState: SUCCESS, data });
},
error => {
dispatch({ args, type, readyState: FAILURE, error });
}
);
};
};
use:
import { createAsyncAction } from 'helpers/async';
import fetch from 'isomorphic-fetch'
// (pretend for a moment that such an action exists)
import { navigate, SIGN_IN } from 'actions/navigation';
// takes args: { subreddit }
function postsWithLikesRequest({ subreddit }) {
// returns a 'thunk promise' that uses dispatch and getState
return function(dispatch, getState) {
const userId = getState().userId;
if(!userId) {
// we have the dispatch function in our async action!
dispatch(navigate(SIGN_IN))
} else {
return fetch(`https://www.reddit.com/r/${subreddit}.json?likes=true&userId=${userId}`)
.then(
response => response.json(),
error => console.log('An error occured.', error)
)
}
}
}
const FETCH_POSTS_WITH_LIKES = 'Actions/Posts/FetchWithLikes';
export const fetchPostsWithLikes = createAsyncAction(FETCH_POSTS_WITH_LIKES, postsWithLikesRequest)
async reducer:
// helpers/async.js
import { combineReducers } from 'redux'; export const createAsyncReducer = (type) => {
const loading = (state = false, action) => {
if (action.type === type) {
return action.readyState === REQUEST;
}
return state;
}; const data = (state = null, action) => {
if (action.type === type) {
return action.data;
}
return state;
}; const error = (state = null, action) => {
if (action.type === type) {
return action.error;
}
return state;
}; return combineReducers({ loading, data, error });
};
use async reducer:
import { createAsyncReducer } from 'helpers/async';
import { FETCH_LATEST_POSTS } from 'actions/posts';
//
// Here's the reducer we can create with the helper
//
export const latestPosts = createAsyncReducer(FETCH_LATEST_POSTS);
//
// It's functionally equivalent to writing all this:
//
export function latestPosts(state = { loading: false, data: null, error: null }, action) {
if(action.type === FETCH_LATEST_POSTS) {
switch(action.readyState) {
case 'request':
return { loading: true, data: null, error: null };
case 'success':
return { loading: false, data: action.data, error: null };
case 'failure':
return { loading: false, data: null, error: action.error };
}
}
return state;
}
5、More configuration
The naive reducer returned by the simple createAsyncReducerfunction above is pretty useful for simple data fetches, but we often want to do more than just store the data from a request.
The actual createAsyncReducer function we use supports swapping in reducers that can respond to different actions or handle the request actions differently.
import {combineReducers} from "redux";
import {FAILURE, REQUEST, SUCCESS} from "constant/ActionType";
export const asyncReducerHelper = (type, reducers = {}) => {
let defaultReducers = {
loading: (state = false, action) => {
if (action.type === type) {
return action.readyState === REQUEST;
}
return state;
},
data: (state = null, action) => {
if (action.type === type && action.readyState === SUCCESS) {
return action.data;
}
return state;
},
error: (state = null, action) => {
if (action.type === type && action.readyState === FAILURE) {
return action.err;
}
return state;
},
};
return combineReducers(Object.assign({}, defaultReducers, reducers));
};
use:
import { createAsyncAction, createAsyncReducer } from 'helpers/async';
// I'm using the fetch api here, but you can substitute any http request libarary.
// For more about the fetch api: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API
const postsRequest = (subreddit) => {
return fetch(`https://www.reddit.com/r/${subreddit}.json`)
.then(
response => response.json(),
error => console.log('An error occured.', error)
)
}
const FETCH_POSTS = 'Actions/Posts/Fetch';
// async action
export const fetchPosts = createAsyncAction(FETCH_POSTS, postsRequest);
// async reducer with shape { loading, data, error }
export const posts = createAsyncReducer(FETCH_POSTS);
react-redux: async promise的更多相关文章
- 在react+redux+axios项目中使用async/await
Async/Await Async/Await是尚未正式公布的ES7标准新特性.简而言之,就是让你以同步方法的思维编写异步代码.对于前端,异步任务代码的编写经历了 callback 到现在流行的 Pr ...
- react+redux教程(五)异步、单一state树结构、componentWillReceiveProps
今天,我们要讲解的是异步.单一state树结构.componentWillReceiveProps这三个知识点. 例子 这个例子是官方的例子,主要是从Reddit中请求新闻列表来显示,可以切换reac ...
- react+redux教程(六)redux服务端渲染流程
今天,我们要讲解的是react+redux服务端渲染.个人认为,react击败angular的真正“杀手锏”就是服务端渲染.我们为什么要实现服务端渲染,主要是为了SEO. 例子 例子仍然是官方的计数器 ...
- react+redux教程(一)connect、applyMiddleware、thunk、webpackHotMiddleware
今天,我们通过解读官方示例代码(counter)的方式来学习react+redux. 例子 这个例子是官方的例子,计数器程序.前两个按钮是加减,第三个是如果当前数字是奇数则加一,第四个按钮是异步加一( ...
- 实例讲解基于 React+Redux 的前端开发流程
原文地址:https://segmentfault.com/a/1190000005356568 前言:在当下的前端界,react 和 redux 发展得如火如荼,react 在 github 的 s ...
- 一个 React & Redux的目录树
|-----------------------------------------| | | | React & Redux | | | |------------------------- ...
- 使用react+redux+react-redux+react-router+axios+scss技术栈从0到1开发一个applist应用
先看效果图 github地址 github仓库 在线访问 初始化项目 #创建项目 create-react-app applist #如果没有安装create-react-app的话,先安装 npm ...
- webpack+react+redux+es6开发模式
一.预备知识 node, npm, react, redux, es6, webpack 二.学习资源 ECMAScript 6入门 React和Redux的连接react-redux Redux 入 ...
- react+redux官方实例TODO从最简单的入门(6)-- 完结
通过实现了增-->删-->改-->查,对react结合redux的机制差不多已经了解,那么把剩下的功能一起完成吧 全选 1.声明状态,这个是全选状态 2.action约定 3.red ...
- react+redux官方实例TODO从最简单的入门(1)-- 前言
刚进公司的时候,一点react不会,有一个需求要改,重构页面!!!完全懵逼,一点不知道怎么办!然后就去官方文档,花了一周时间,就纯react实现了页面重构,总体来说,react还是比较简单的,由于当初 ...
随机推荐
- Android View学习Tips
1.Canvas.save()和Canvas.restore() canvas.save();和canvas.restore();是两个相互匹配出现的,作用是用来保存画布的状态和取出保存的状态的.这里 ...
- web项目的getContextPath()
伯乐一看小编的这个博文的标题是不是觉得有些小,以点到面,知道了web中getContextPath()这种获取路径的方式,显然其他的方式的是可以以此类推的.常说,工作学习找共同点嘛. 上一段我们也提高 ...
- go——基本构成要素
Go的语言符号又称为词法元素,共包括5类内容: 标识符(identifier) 关键字(keyword) 字面量(literal) 分隔符(delimiter) 操作符(operator)它们可以组成 ...
- 微信小程序组件text
基础内容text:官方文档 Demo Code var initData = 'this is first line\nthis is second line' var extraLine = []; ...
- js高级---js运行原理
概述 浏览器组成可分两部分:Shell+内核.浏览器内核又可以分成两部分:渲染引擎(layout engineer或者Rendering Engine)和JS引擎.渲染引擎功能作用 渲染引擎,负责对网 ...
- DataNode启动不成功——java.net.BindException: Port in use: localhost:0 Caused by: java.net.BindException: Cannot assign requested address解决办法
爱折腾的人总是会出线各种奇怪的问题.记得之前听一位大师讲过,我们不能踩完前进路上的所有坑前进,而应该学会怎样避开前进路上的坑,踩得坑越多,可能你的经验越丰富,但是付出的时间代价可能不是经验能换来的.我 ...
- powerdesigner解决创建多个表表主键名称重复的问题
选择菜单栏的tools选项,选择Model Options..,选择Model Settings 只要将图片中的选择打钩去掉即可(操作步骤1),同时设置为默认选项(操作步骤2),防止以后问题又出现 ...
- JAVA发送HttpClient
http://bijian1013.iteye.com/blog/2310211 在发送HTTP请求的时候会使用到POST和GET两种方式,如果是传送普通的表单数据,我们直接将参数到一个Key-val ...
- LigerUI LigerGird IE7/8 下不显示 “in”的操作数无效
LigerUI IE7/8 下显示 in的操作数无效 修改脚本生成LigerGrid的地方,将最后一列后面的,去掉
- [原创] 毕设---在myeclipes中安装Hadoop开发插件
1.安装Hadoop开发插件 hadoop安装包contrib/目录下有个插件hadoop-0.20.2-eclipse-plugin.jar,拷贝到myeclipse根目录下/dropins目录下. ...