2-6 首页异步数据获取

前面我们把首页中的数据,都定义在了 reducer.js 中,现在,我们将这个数据放在远程,通过ajax 从接口中获取。当然是mock 数据。

首页的数据,我们把它的接口定义为 "/api/home.json" 

然后返回数据大致是这样的:

{
 success: true,
 data: {
   topicList: [{
        id: 1,
        title: '热点--',
        imgURL: '//upload.jianshu.io/users/upload_avatars/4802366/4f86b75d-b61b-4126-8be4-87a151c9cd28.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp'
    }],
    articleList: [{
        id: 1,
        title: '这是标题',
        desc: '这个段落的概要的内容。。。',
        imgURL: '//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240'
    }],
    recommendList: [{
        id: 1,
        imgURL: "http://m.360buyimg.com/babel/jfs/t1/32844/24/9280/5497/5ca56eccEf17f316e/f6810e3e0fb865ed.png"
    }]
 }
}

好的,知道了接口地址与数据结构。那么我们来mock 数据。

先,下载 mockjs (之前已经安装过了在项目里,跳过)

yarn add mockjs

然后在src 下新建一个文件 mockdata.js(已有,跳过)

我们的mockdata.js 如下。

import Mock from 'mockjs';

Mock.mock("/api/headerList.json",{
  "success": true,
  "data": [
    "风格", "水波", "可以","蓝色","红色","黄色","白色","黑色","紫色","绿色",
    "秦始皇","汉武帝","盘古","女娲","黄帝","炎帝","伏羲","雷神","大禹","龙王",
    "呼兰河"    
  ]
});

Mock.mock("/api/home.json", {
  "success" : true,
  "data": {
    "topicList": [{
      "id": 1,
      "title": "热点--",
      "imgURL": "//upload.jianshu.io/users/upload_avatars/4802366/4f86b75d-b61b-4126-8be4-87a151c9cd28.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp"
    }, {
      "id": 2,
      "title": "桃花--",
      "imgURL": '//upload.jianshu.io/users/upload_avatars/3136195/484e32c3504a.jpg?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96/format/webp"
    }],
    "articleList": [{
      "id": 1,
      "title": "这是标题",
      "desc": "这个段落的概要的内容。。。",
      "imgURL": "//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
    },{
      "id": 2,
      "title": "这是标题2",
      "desc": "这个段落的概要的内容2。。。",
      "imgURL": "//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
    }],
    "recommendList": [{
      "id": 1,
      "imgURL": "http://m.360buyimg.com/babel/jfs/t1/32844/24/9280/5497/5ca56eccEf17f316e/f6810e3e0fb865ed.png"
    }, {
      "id": 2,
      "imgURL": "http://m.360buyimg.com/babel/jfs/t1/32844/24/9280/5497/5ca56eccEf17f316e/f6810e3e0fb865ed.png"
    }]
  }
});

然后,我们可以把src/pages/home/store 下的 reducer.js 中的初始数据置空,如下。

import { fromJS } from 'immutable';

const defaultState = fromJS({
    topicList: [],
    articleList: [],
    recommendList: []
});

export default (state = defaultState, action) => {
    switch (action.type) {
        default:
            return state;
    }
}

然后,我们需要在组件中去发送ajax 请求,打开 src/pages/home 下的 index.js ,我们在组件的 componentDidMount 生命周期函数中发送这个请求。如下。

import React, {Component} from 'react';
import {HomeWrapper, HomeLeft, HomeRight } from './style';
import List from './components/List';
import Recommend from './components/Recommend';
import Topic from './components/Topic';
import Writer from './components/Writer';
import bannerImage from '../../statics/ooo.jpg';
import axios from 'axios';

class Home extends Component {
    render () {
        return (
            <HomeWrapper>
                <HomeLeft>
                    <img
                        className="banner-img"
                        src={bannerImage}
                        alt=''
                    />
                    <Topic></Topic>
                    <List></List>
                </HomeLeft>
                <HomeRight>
                    <Recommend></Recommend>
                    <Writer></Writer>
                </HomeRight>
            </HomeWrapper>
        )
    }
    componentDidMount () {
        axios.get("/api/home.json").then((res) => {
            console.log(res);
        })
    }
}

export default Home;

接下来,我们要把获得的数据,放到redux 中。先在home 组件中发送action 。

import React, {Component} from 'react';
import { connect } from 'react-redux';
import {HomeWrapper, HomeLeft, HomeRight } from './style';
import List from './components/List';
import Recommend from './components/Recommend';
import Topic from './components/Topic';
import Writer from './components/Writer';
import bannerImage from '../../statics/ooo.jpg';
import axios from 'axios';
import { dispatch } from 'C:/Users/ThinkPad/AppData/Local/Microsoft/TypeScript/3.4/node_modules/rxjs/internal/observable/range';

class Home extends Component {
    render () {
        return (
            <HomeWrapper>
                <HomeLeft>
                    <img
                        className="banner-img"
                        src={bannerImage}
                        alt=''
                    />
                    <Topic></Topic>
                    <List></List>
                </HomeLeft>
                <HomeRight>
                    <Recommend></Recommend>
                    <Writer></Writer>
                </HomeRight>
            </HomeWrapper>
        )
    }
    componentDidMount () {
        axios.get("/api/home.json").then((res) => {
            const result = res.data.data;
            const action = {
                type: "change_home_data",
                topicList: result.topicList,
                articleList: result.articleList,
                recommendList: result.recommendList
            };
            this.props.changeHomeData(action);
        })
    }
}

const mapDispatch = (dispatch) => {
    return {
        changeHomeData (action) {
            dispatch(action);
        }
    }
}
export default connect(null, mapDispatch)(Home);

我们在上面中dispatch 派发的action,除了总的 reducer 能收到外,所有小的reducer 也能收到。也就是说。src/pages/home/store 下的reducer 也能接收到这个action 。然后我们可以在src/pages/home/store 下的reducer做如下修改。

import { fromJS } from 'immutable';

const defaultState = fromJS({
    topicList: [],
    articleList: [],
    recommendList: []
});

export default (state = defaultState, action) => {
    switch (action.type) {
        case "change_home_data":
            state.set("topicList", fromJS(action.topicList));
            state.set("articleList", fromJS(action.articleList));
            state.set("recommendList", fromJS(action.recommendList));
            return state;
        default:
            return state;
    }
}

上面,连写三个 set 可以更简便:

import { fromJS } from 'immutable';

const defaultState = fromJS({
    topicList: [],
    articleList: [],
    recommendList: []
});

export default (state = defaultState, action) => {
    switch (action.type) {
        case "change_home_data":
            return state.merge({
                "topicList": fromJS(action.topicList),
                "articleList": fromJS(action.articleList),
                "recommendList": fromJS(action.recommendList)
            });
        default:
            return state;
    }
}

Done!

猜你喜欢

转载自blog.csdn.net/purple_lumpy/article/details/89306081
2-6