加载更多,就在在首页的底部有一个加载更多按钮,当点击它时,就能加载更多的 list 。
由于它主要是加载更多的 list,因此,我们把加载更多放到 src/pages/home 下的 List.js 组件中。
下面是 List.js 代码。
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { ListItem, ListInfo, LoadMore } from '../style';
class List extends Component {
render () {
const { articleList } = this.props;
return (
<div>
{
articleList.map( (item) => {
return (
<ListItem key={item.get('id')}>
<img
className='pic'
src={item.get('imgURL')}
alt=''
/>
<ListInfo>
<h3 className='title'>{item.get('title')}</h3>
<p className='desc'>{item.get('desc')}</p>
</ListInfo>
</ListItem>
)
} )
}
<LoadMore>更多文字</LoadMore>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
articleList: state.get("home").get("articleList")
}
}
export default connect(mapStateToProps, null)(List);
下面是src/pages/home 下的 style.js 中添加的内容
export const LoadMore = styled.div`
width: 100%;
height: 40px;
margin: 30px 0;
line-height: 40px;
background: #a5a5a5;
text-align: center;
border-radius: 20px;
color: #fff;
cursor: pointer;
`;
然后,我们给这个小组件一个点击事件,并使它的点击事件派发一个action,如下
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { ListItem, ListInfo, LoadMore } from '../style';
import { actionCreators } from '../store';
class List extends Component {
render () {
const { articleList, getMoreList } = this.props;
return (
<div>
{
articleList.map( (item) => {
return (
<ListItem key={item.get('id')}>
<img
className='pic'
src={item.get('imgURL')}
alt=''
/>
<ListInfo>
<h3 className='title'>{item.get('title')}</h3>
<p className='desc'>{item.get('desc')}</p>
</ListInfo>
</ListItem>
)
} )
}
<LoadMore onClick={getMoreList}>更多文字</LoadMore>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
articleList: state.get("home").get("articleList")
}
};
const mapDispatchToProps = (dispatch) => {
return {
getMoreList () {
dispatch(actionCreators.getMoreList());
}
}
};
export default connect(mapStateToProps, mapDispatchToProps)(List);
然后,我们去 actionCreators 中去创建这个action ,如下。
我们定义这个的请求接口为 “/api/homeList.json” 。
并在 src/mockdata.js 文件中添加这个 mock 数据如下。
Mock.mock("/api/homeList.json", {
"success" : true,
"data": {
"articleList": [{
"id": 3,
"title": "这是标题3",
"desc": "这个段落的概要的内容3。。。",
"imgURL": "//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
},{
"id": 4,
"title": "这是标题4",
"desc": "这个段落的概要的内容4。。。",
"imgURL": "//upload-images.jianshu.io/upload_images/13910150-3c33a8d64aa623bc.png?imageMogr2/auto-orient/strip|imageView2/1/w/360/h/240"
}]
}
});
然后我们在actionCreators.js 中添加action
import axios from 'axios';
import { fromJS } from 'immutable';
import * as actionTypes from './actionTypes';
const changeHomeData = (result) => ({
type: actionTypes.CHANGE_HOME_DATA,
topicList: result.topicList,
articleList: result.articleList,
recommendList: result.recommendList
});
const addHomeList = (result) => ({
type: actionTypes.ADD_ARTICLE_LIST,
articleList: fromJS(result.articleList)
})
export const getHomeInfo = () => {
return (dispatch) => {
axios.get("/api/home.json").then((res) => {
const result = res.data.data;
const action = changeHomeData(result);
dispatch(action);
});
}
}
export const getMoreList = () => {
return (dispatch) => {
axios.get("/api/homeList.json").then((res) => {
const result = res.data.data;
const action = addHomeList(result);
dispatch(action);
})
}
}
添加一个actionType,actionTypes.js 如下
export const CHANGE_HOME_DATA = 'home/change_home_data';
export const ADD_ARTICLE_LIST = 'home/add_article_list';
然后在reducer (src/pages/home/store/reducer.js) 中增加一个case,如下。
import { fromJS } from 'immutable';
import * as actionTypes from './actionTypes';
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: []
});
export default (state = defaultState, action) => {
switch (action.type) {
case actionTypes.CHANGE_HOME_DATA:
return state.merge({
"topicList": fromJS(action.topicList),
"articleList": fromJS(action.articleList),
"recommendList": fromJS(action.recommendList)
});
case actionTypes.ADD_ARTICLE_LIST:
return state.set("articleList", state.get("articleList").concat(action.articleList));
default:
return state;
}
}
好的。
然后有一点,在实际开发中,我们是会把点击加载更多List 的数据做分页的。点击一次,就要告诉后端要第几页的数据。
下面就来实现一下这个分页。
首页在src/pages/home/store/reducer 中新建一个数据项 articlePage 默认值为 1。
import { fromJS } from 'immutable';
import * as actionTypes from './actionTypes';
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: [],
articlePage: 1
});
export default (state = defaultState, action) => {
switch (action.type) {
case actionTypes.CHANGE_HOME_DATA:
return state.merge({
"topicList": fromJS(action.topicList),
"articleList": fromJS(action.articleList),
"recommendList": fromJS(action.recommendList)
});
case actionTypes.ADD_ARTICLE_LIST:
return state.set("articleList", state.get("articleList").concat(action.articleList));
default:
return state;
}
}
然后,回到src/pages/home/components 下的 List.js 我们要在组件中获取这个数据。
import React, {Component} from 'react';
import { connect } from 'react-redux';
import { ListItem, ListInfo, LoadMore } from '../style';
import { actionCreators } from '../store';
class List extends Component {
render () {
const { articleList, getMoreList, articlePage } = this.props;
return (
<div>
{
articleList.map( (item) => {
return (
<ListItem key={item.get('id')}>
<img
className='pic'
src={item.get('imgURL')}
alt=''
/>
<ListInfo>
<h3 className='title'>{item.get('title')}</h3>
<p className='desc'>{item.get('desc')}</p>
</ListInfo>
</ListItem>
)
} )
}
<LoadMore onClick={ () => getMoreList(articlePage)}>更多文字</LoadMore>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
articleList: state.get("home").get("articleList"),
articlePage: state.get("home").get("articlePage")
}
};
const mapDispatchToProps = (dispatch) => {
return {
getMoreList (page) {
dispatch(actionCreators.getMoreList(page));
}
}
};
export default connect(mapStateToProps, mapDispatchToProps)(List);
然后在 src/pages/home/store 下的 actionCreators.js 中修改一下。
import axios from 'axios';
import { fromJS } from 'immutable';
import * as actionTypes from './actionTypes';
const changeHomeData = (result) => ({
type: actionTypes.CHANGE_HOME_DATA,
topicList: result.topicList,
articleList: result.articleList,
recommendList: result.recommendList
});
const addHomeList = (result, page) => ({
type: actionTypes.ADD_ARTICLE_LIST,
articleList: fromJS(result.articleList),
page: page
})
export const getHomeInfo = () => {
return (dispatch) => {
axios.get("/api/home.json").then((res) => {
const result = res.data.data;
const action = changeHomeData(result);
dispatch(action);
});
}
}
export const getMoreList = (page) => {
return (dispatch) => {
axios.get("/api/homeList.json?page=" + page).then((res) => {
const result = res.data.data;
const action = addHomeList(result, page + 1);
dispatch(action);
})
}
}
然后,我们修改一下 src/pages/home/store 下的reducer,如下。
import { fromJS } from 'immutable';
import * as actionTypes from './actionTypes';
const defaultState = fromJS({
topicList: [],
articleList: [],
recommendList: [],
articlePage: 1
});
export default (state = defaultState, action) => {
switch (action.type) {
case actionTypes.CHANGE_HOME_DATA:
return state.merge({
"topicList": fromJS(action.topicList),
"articleList": fromJS(action.articleList),
"recommendList": fromJS(action.recommendList)
});
case actionTypes.ADD_ARTICLE_LIST:
return state.merge({
"articleList": state.get("articleList").concat(action.articleList),
"articlePage": action.page
})
default:
return state;
}
}
Done.