当前位置: 首页 > news >正文

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);

 

转载于:https://www.cnblogs.com/Nyan-Workflow-FC/p/9316402.html

相关文章:

  • Esper——内存计算、事件驱动、SQL支持
  • 梯度下降,牛顿法 ,高斯牛顿法
  • 小程序实践(八):验证码倒计时功能
  • CSS 提示工具(Tooltip)
  • 开放平台下从事开发工作的苦水
  • BigDecimal的用法详解(保留两位小数,四舍五入,数字格式化,科学计数法转数字,数字里的逗号处理)...
  • 分发系统介绍、 expect脚本远程登录、远程执行命令、传递参数
  • 欧几里得扩展算法扩展欧几里得
  • Spring Boot 2.0 整合 ES 5 文章内容搜索实战
  • HyperLedger Fabric ca正式环境部署
  • mysql-ubuntu14.04彻底卸载mysql
  • 检测对象或数组
  • Python--作业2--对员工信息文件,实现增删改查操作
  • BAT面试常的问题和最佳答案
  • MFS分布式文件系统服务搭建
  • 【面试系列】之二:关于js原型
  • java 多线程基础, 我觉得还是有必要看看的
  • java中的hashCode
  • Node项目之评分系统(二)- 数据库设计
  • PV统计优化设计
  • React-Native - 收藏集 - 掘金
  • Redis 中的布隆过滤器
  • scrapy学习之路4(itemloder的使用)
  • vue.js框架原理浅析
  • 鱼骨图 - 如何绘制?
  • #AngularJS#$sce.trustAsResourceUrl
  • $.ajax,axios,fetch三种ajax请求的区别
  • (1)Android开发优化---------UI优化
  • (12)Hive调优——count distinct去重优化
  • (分布式缓存)Redis持久化
  • (附源码)springboot 房产中介系统 毕业设计 312341
  • (附源码)springboot建达集团公司平台 毕业设计 141538
  • (附源码)SSM环卫人员管理平台 计算机毕设36412
  • (接口封装)
  • (切换多语言)vantUI+vue-i18n进行国际化配置及新增没有的语言包
  • (算法设计与分析)第一章算法概述-习题
  • (轉貼) VS2005 快捷键 (初級) (.NET) (Visual Studio)
  • .Net Core 中间件验签
  • .NET Micro Framework 4.2 beta 源码探析
  • .net 后台导出excel ,word
  • .NET 中选择合适的文件打开模式(CreateNew, Create, Open, OpenOrCreate, Truncate, Append)
  • .NET/C# 的字符串暂存池
  • .NET/C# 反射的的性能数据,以及高性能开发建议(反射获取 Attribute 和反射调用方法)
  • .net生成的类,跨工程调用显示注释
  • [ 2222 ]http://e.eqxiu.com/s/wJMf15Ku
  • [ web基础篇 ] Burp Suite 爆破 Basic 认证密码
  • [8-23]知识梳理:文件系统、Bash基础特性、目录管理、文件管理、文本查看编辑处理...
  • [Angular] 笔记 6:ngStyle
  • [bzoj1038][ZJOI2008]瞭望塔
  • [BZOJ1053][HAOI2007]反素数ant
  • [BZOJ2281][SDOI2011]黑白棋(K-Nim博弈)
  • [C]整形提升(转载)
  • [CentOs7]图形界面
  • [datastore@cyberfear.com].Elbie、[thekeyishere@cock.li].Elbie勒索病毒数据怎么处理|数据解密恢复
  • [Django 0-1] Core.Checks 模块