• 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);
  • 相关阅读:
    有效管理时间的十八种方法
    针对某个块下面的按钮注册点击事件
    vs2015运行项目时出现“编译器失败,错误代码为 1”的解决方案
    淘宝API调用 申请 获取session key
    中小型研发团队架构实践:生产环境诊断利器WinDbg帮你快速分析异常情况Dump文件
    中小型研发团队架构实践:如何规范公司所有应用分层?
    中小型研发团队架构实践:电商如何做企业总体架构?
    中小型研发团队架构实践:高效率、低风险,一键发布并测试的持续集成工具Jenkins
    ASP.NET全栈开发验证模块之在Vue中使用前端校验
    计算机基础存储结构
  • 原文地址:https://www.cnblogs.com/Nyan-Workflow-FC/p/9316402.html
Copyright © 2020-2023  润新知