dva 如何异步获取接口数据

说在前面

  • 关于redux的框架有很多,这里我用到的是阿里云谦大大的dva(项目地址),这里主要记录下工作中是如何使用dva来异步获取接口数据的。
  • 文末更新至20190619

更新(2019.0619)

  • 最近发现这篇文章虽然写的很烂,但是很多人都能搜到进来瞅两眼,想着再更新一点吧。主要补充一下dva的几个关键词的作用
state的作用
  • State 表示 Model 的状态数据,通常表现为一个 javascript 对象(当然它可以是任何值);操作的时候每次都要当作不可变数据(immutable data)来对待,保证每次都是全新对象,没有引用关系,这样才能保证 State 的独立性,便于测试和追踪变化。
  • 在每一个model中定义state,用于分模块管理全局状态
effects的作用
  • 进行异步操作的地方(ajax...),底层引入了redux-sagas做异步流程控制,由于采用了generator的相关概念,所以将异步转成同步写法
  • 类似于vuex中的Action,包含异步操作,在vuex中用于提交mutation,从而变更state,在dva中用于提交reducer,用于修改state
Reducer的作用
  • 同步方法,唯一可以修改state的地方,通过effect通过actions传入的值修改state
  • 类似于vuexmutation
Subscription的作用
  • 订阅一个数据源,然后根据条件 dispatch 需要的 action。数据源可以是当前的时间、服务器的 websocket 连接、keyboard 输入、geolocation 变化、history 路由变化等等。
payload关键字
  • 一般作为参数含义,由UI层通过dispatch一个payload参数在model文件中使用
call
  • 结合yield call发起ajax请求
//getDetailDiscount 接口名
//payload 参数
yield call(getDetailDiscount, payload)
put
  • 使用put关键词提交Reducer
//doDiscounts 一个名字为doDiscounts的同步方法 修改state
yield put({type: 'doDiscounts', payload: response.data});
select
  • effect中可以通过select获取modelstate
  • 定义state
 state:{
     num:1
 }
  • 定义effect
 effect:{
     *getNum({payload},{select}){
         //获取state中的num
         const num = yield select(state => state.num) 
     }
 }
  • model获取state

other字段为modelnamespace

 effect:{
     *getOtherNum({payload},{select}){
         //获取state中的num
         const num = yield select(state => state.other.num) 
     }
 }

这里是正文

第一步、定义model

dva里的model主要是用来开始处理数据和逻辑的。
dva 通过 model 的概念把一个领域的模型管理起来,包含同步更新 state 的 reducers,处理异步逻辑的 effects,订阅数据源的 subscriptions 。

新建一个一个model/users.js

export default {
  namespace: 'users',
  state: [],
  reducers: {
     doSearch (state, { payload}){
      return {
        ...state,
        searchRsp: payload.data,
      }
    },
  },
  effects:{
  * handleGetSearch({payload, searchRspCallBack}, {call, put}) {
      LogTag('****************************handleGetSearch req*************', payload);
      const response = yield call(getSearch, payload);
      LogTag('****************************handleGetSearch rsp*************', response);
      if (response.status === 200 && response.data.status === 0) {
        searchRspCallBack(response.data.result)
      } else if (response.status === 200 && response.data.status === 1) {
        message.error(response.data.msg)
        yield put({
          type: 'doSearch',
          payload: response.data,
        });
      }
      
  },
  subscriptions :{
      
  }
};

新建ApiService.js文件

import request from '../utils/request';
import {stringify} from 'qs';
/*
* 搜索
* */
export async function getSearch(params) {
  return request(`/search?${stringify(params)}`);
}

这里我主要在effects 定义了一个handleGetSearch方法,
这个方法简单理解:

1、paload是接口的参数,这里打印一下
2、searchRspCallBack是一个回调方法,
  主要是在接口正常调用之后将响应内容在页面层使用
3、yield call(getSearch, payload);是一个异步调用接口参数的方法
4、上述中的if判断主要是说在接口响应到的数据为我与后台正确定义的返回码才进行相应的操作,
比如这里我跟后台约定的是status === 0正常 status === 1 打印后台返回的错误信息
5、searchRspCallBack(response.data.result)
  调用传过来的回调将接口返回数据作为参数传进去

reducers方法:用于执行同步操作,改变state等

return {
    ...state,
    searchRsp: payload.data,
    }
改变model中state的searchRsp值为接口返回的响应内容

第二步、使用model中的方法

model中异步获取数据的方法定义好之后如何使用呢?

this.props.dispatch({
      type: 'users/handleGetSearch',
      payload: {
        keywords: this.state.searchText,
        limit: this.state.limit
      },
      searchRspCallBack: this.handleSearchRspCallBack
})

handleSearchRspCallBack = (rsp)=>{
    LogTag(rsp)
}


这是dva中使用dispatch调用model中方法的写法,注意在使用此方法之前要先使用 connect将model与component连接起来,如果你熟悉 redux,这个 connect 就是 react-redux 的 connect 。

这里使用注解的方法使用connect

@connect(({users, loading}) => ({
  users,
}))

上述dispatch的简单解释:

1、type为要调用的哪个model中的哪个方法,

2、payload为传的参数,这里传了一个keyword与limit数量过去

3、searchRspCallBack: this.handleSearchRspCallBack的意思是将本地的一个方法作为参数传递到model中,
如果model中正确响应之后将响应的内容作为参数传递到这个方法中,
然后我本地写一个handleSearchRspCallBack方法用来接收响应
这样我在component层就可以拿到接口响应的内容了

这是我用来获取接口异步数据的方法第一种,还有一种就是之前在model中执行了reducer同步方法将接口返回的数据保存在了model中的state里面,在componentWillReceiveProps钩子函数也可以拿到我们需要的响应

componentWillReceiveProps(nextProps){
    if(nextProps){
      LogTag(nextProps.users.searchRsp)
    }
  }

上述中nextProps.users.searchRsp就是接口返回的值了

简单的总结

1、先在model中定义一个方法用来执行异步调用接口的方法,可以直接使用回调方法的方法将响应作为参数回调,也可以使用同步reducer的方法将数据保存在state中,后面component层去取model中state的值

2、两种方法都可以获取到异步调用接口返回的响应,第一种好需要定义一个回调方法,第二种获取model中state值需要定义state,在不同的场景使用不同的方法

文章补充:2019.6.1

  • 使用callback非常的不优美,这里官方其实早已提供promise的写法
    *handleUpdateBasicInfo({ payload, user }, { call, put, select }){
      const response = yield call(postUpdateBasicInfo, payload);
      if (response && response.status === 0) {
        return response.data
      }
    },
    //这里在effect中直接return 我们想知道的结果
    
    handleUpdateBasicInfo = (params) => {
    const { dispatch } = this.props;
    dispatch({
      type: 'user/handleUpdateBasicInfo',
      payload: {
        ...params,
      },
    }).then(res=>{
      console.log('res',res)
    })
  };
  //这里then中可以获取到数据


原文首发

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,496评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,407评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,632评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,180评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,198评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,165评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,052评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,910评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,324评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,542评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,711评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,424评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,017评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,668评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,823评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,722评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,611评论 2 353

推荐阅读更多精彩内容