9.3 异步获取数据
前面实现了用redux来存储详情页面的内容。
但是,实际情况中,详情页面的内容需要通过异步操作来获取,本节将介绍异步获取数据的步骤。
一、编写index.js
- 在生命周期函数componentDidMount中调用getDetail异步方法;
- 写mapDispatch方法框架,并最后把connect中的第二个值替换成mapDispatch;
- 在顶部引用actionCreators ;
- 在mapDispatch中,调用dispatch方法发一个actionCreators.getDetail()这样的一个action出去;
- 最终index代码如下:
//detail/index.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { DetailWrapper, Content, Header } from'./style';
import { actionCreators } from './store'; //3.引用actionCreators
class Detail extends Component {
render() {
return (
<DetailWrapper>
<Header>{this.props.title}</Header>
<Content dangerouslySetInnerHTML={{__html: this.props.content}} />
</DetailWrapper>
)
}
componentDidMount() { //1.在生命周期函数componentDidMount中调用getDetail异步方法
this.props.getDetail();
}
}
const mapState = (state) => ({
title: state.getIn(['detail', 'title']),
content: state.getIn(['detail', 'content'])
})
const mapDispatch = (dispatch) => ({ //2.1 写mapDispatch方法框架
getDetail() {
dispatch(actionCreators.getDetail()) //在mapDispatch中,调用dispatch方法发一个action
}
})
export default connect(mapState, mapDispatch)(Detail); //2.2 替换connect中的第二个值
二、准备detail.json接口文档
//api/detail.json的例子
{
"success": true,
"data": {
"title": "岁月沧桑,从不荒凉",
"connect": "<h4>这世上最难走的路,叫生活,我们一路跌倒,一路坚强,任尘世流转,岁月沧桑,内心安然无恙。</h4><h4>三毛说:“人生如茶,第一道苦若生命,第二道甜似爱情,第三道淡如清风。” 其实,生命就是一个不断寻找,不断历练,不断感悟的过程,从最初的天真单纯,到百炼成钢,再到最后的云水禅心,是悟,亦是成长。</h4><img src='//upload-images.jianshu.io/upload_images/8733570-14afcb7ca90d1230.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/640/format/webp' /><h4>岁月沧桑,我依然坚强。坚强,是百折不挠的勇气,是跌倒之后的奋起,是世间最强大的力量,也是生命的希望。生活的酸甜苦辣,每个人都要品尝一遭,再苦再累,也要坚强,为自己,也为那些爱自己的人。</h4><h4>岁月沧桑,我依然善良。大千世界,芸芸众生,每个人都不尽相同,你不懂他的苦,他亦不懂你的痛,以一颗慈悲心相处,对身边的人和事,多些宽容。善良是一个人最伟大的情怀,是自我修养的提高,你的善良,万丈光芒。</h4>"
}
}
三、修改actionCreation,编写constants
- 导入axios方法,并且在return中调用axios方法去获取某个接口数据,并通过dispatch传递信息;
- 在constants中写CHANGE_DETAIL = ‘detail/CHANGE_DETAIL’;
- 写changeDetail
- 导入constants,有了constants文件,type就可以直接这样写constants.CHANGE_DETAIL;
可以在dispatch方法前用console.log()方法检查result的值符不符合预期,不符合就说明代码有问题,重点检查.json文件内接口规范;
//detail/store/actionCreation.js
import axios from 'axios'; //1.1导入axios方法
import * as constants from './constants'; //4.1导入constants
const changeDetail = (title, content) => ({ //编写changeDetail方法,该方法用来合成一个action
type: constants.CHANGE_DETAIL, //4.2有了constants文件,type就可以直接这样写
title,
content
})
export const getDetail = () => {
return (dispatch) => {
axios.get('/api/detail.json').then((res) => { //1.2在return中调用axios方法
const result = res.data.data; //变量result用来存接口文档中的data数据
dispatch(changeDetail(result.title, result.content)); //传递result.title, result.content给changeDetail方法
}) //最终合成成为action后再dispatch走
}
}
//detail/store/constants.js
export const CHANGE_DETAIL = 'detail/CHANGE_DETAIL'; //2.等价替换
四、修改reducer
- 新增一个case,当传入的action中的type匹配时(即当前动作类型为更改详情页),则执行return中的内容——更新state的数据;
//detail/store/reducer.js
import {fromJS} from 'immutable';
import * as constants from './constants';
const defaultState = fromJS({
title: '',
content: ''
})
export default (state = defaultState, action) => {
switch (action.type) {
case constants.CHANGE_DETAIL: //新增一个case,当传入的action中的type匹配时,运行下方return
return state.merge({ //merge方法用来更新state的数据
title: action.title,
content: action.content
}
)
default:
return state;
}
}
- 到浏览器中看看能否正常显示详情页的内容: