Authored by 于良

处理版块首页在导航栈中多次出现时的情况 review by 盖剑秋

... ... @@ -79,6 +79,8 @@ class SectionContainer extends React.Component {
this._onUploadRetry = this._onUploadRetry.bind(this);
this._onUploadDelete = this._onUploadDelete.bind(this);
this._onUploadSuccess = this._onUploadSuccess.bind(this);
this.sid = this.props.section.sid;
}
componentDidMount() {
... ... @@ -92,7 +94,7 @@ class SectionContainer extends React.Component {
Actions.refresh({key: 'Home', showNativeTabBar: true});
}
this.props.actions.sectionClean();
this.props.actions.sectionClean(this.sid);
}
_onPressBanner(url) {
... ... @@ -114,7 +116,7 @@ class SectionContainer extends React.Component {
_onPressSectionTag(section) {
console.log('section tag');
this.props.actions.goToSection(section)
this.props.actions.goToSection(section);
}
_onPressComment(url) {
... ... @@ -127,20 +129,19 @@ class SectionContainer extends React.Component {
_onRefresh() {
InteractionManager.runAfterInteractions(() => {
this.props.actions.header();
this.props.actions.hotPost(true);
this.props.actions.newPost(true);
// this.props.actions.setActiveTab(0);
this.props.actions.header(this.sid);
this.props.actions.hotPost(this.sid, true);
this.props.actions.newPost(this.sid, true);
});
}
_onEndReached(page) {
InteractionManager.runAfterInteractions(() => {
this.props.actions.setActiveTab(page);
this.props.actions.setActiveTab(this.sid, page);
if (page === 1) {
this.props.actions.hotPost(false);
this.props.actions.hotPost(this.sid, false);
} else {
this.props.actions.newPost(false);
this.props.actions.newPost(this.sid, false);
}
});
}
... ... @@ -196,7 +197,10 @@ class SectionContainer extends React.Component {
}];
}
progressing = Immutable.fromJS(progressing);
let {activeTab, new: newPost, hot: hotPost, header, notice, ptr, isFetching : bnsIsFetching} = this.props.section;
let section = this.props.section.items.get(this.sid);
let {activeTab, new: newPost, hot: hotPost, header, notice, ptr, isFetching : bnsIsFetching} = section;
let isRefreshing, isLoadingMore, isFetching, endReached;
if (activeTab === 0) {
... ...
... ... @@ -38,6 +38,14 @@ const {
} = require('../../constants/actionTypes').default;
export function goToSection(section) {
Actions.Section();
return {
type: GO_TO_SECTION,
payload: section,
};
}
export function goToUserOrMe(uid) {
return (dispatch, getState) => {
... ... @@ -256,14 +264,6 @@ export function resetErrorCount() {
};
}
export function goToSection(section) {
Actions.Section();
return {
type: GO_TO_SECTION,
payload: section,
};
}
function parseBNS(json) {
let {resourceList, forumInfo} = json;
let {advertList, textNoticeList} = resourceList;
... ...
... ... @@ -68,8 +68,7 @@ export default function homeReducer(state = initialState, action) {
case HOME_RECOMMENDATION_REQUEST: {
let nextState = state.setIn(['recommendation', 'isFetching'], true)
.setIn(['recommendation', 'error'], null)
.set('ptr', action.payload);
.setIn(['recommendation', 'error'], null);
return nextState;
}
... ...
... ... @@ -28,81 +28,85 @@ const {
SECTION_CLEAN,
} = require('../../constants/actionTypes').default;
export function headerRequest() {
export function headerRequest(sid) {
return {
type: SECTION_HEADER_REQUEST,
payload: sid
};
}
export function headerSuccess(json) {
export function headerSuccess(sid, json) {
return {
type: SECTION_HEADER_SUCCESS,
payload: json
payload: {sid, json}
};
}
export function headerFailure(error) {
export function headerFailure(sid, error) {
return {
type: SECTION_HEADER_FAILURE,
payload: error
payload: {sid ,error}
};
}
export function newPostRequest(ptr) {
export function newPostRequest(sid, ptr) {
return {
type: SECTION_NEW_POST_REQUEST,
payload: ptr,
payload: {sid, ptr},
};
}
export function newPostSuccess(json) {
export function newPostSuccess(sid, json) {
return {
type: SECTION_NEW_POST_SUCCESS,
payload: json
payload: {sid, json}
};
}
export function newPostFailure(error) {
export function newPostFailure(sid, error) {
return {
type: SECTION_NEW_POST_FAILURE,
payload: error
payload: {sid, error}
};
}
export function hotPostRequest(ptr) {
export function hotPostRequest(sid, ptr) {
return {
type: SECTION_HOT_POST_REQUEST,
payload: ptr,
payload: {sid, ptr},
};
}
export function hotPostSuccess(json) {
export function hotPostSuccess(sid, json) {
return {
type: SECTION_HOT_POST_SUCCESS,
payload: json
payload: {sid, json}
};
}
export function hotPostFailure(error) {
export function hotPostFailure(sid, error) {
return {
type: SECTION_HOT_POST_FAILURE,
payload: error
payload: {sid, error}
};
}
export function header() {
export function header(sid) {
return (dispatch, getState) => {
let {section} = getState();
if (section.isFetching) {
let item = section.items.get(sid);
if (item.isFetching) {
return;
}
dispatch(headerRequest());
return new SectionService().header(section.id)
dispatch(headerRequest(sid));
return new SectionService().header(item.id)
.then(json => {
let payload = parseHeader(json);
dispatch(headerSuccess(payload));
dispatch(headerSuccess(sid, payload));
})
.catch(error => {
dispatch(headerFailure());
dispatch(headerFailure(sid, error));
});
};
}
... ... @@ -125,9 +129,10 @@ export function header() {
// };
// }
export function newPost(ptr = false) {
export function newPost(sid, ptr = false) {
return (dispatch, getState) => {
let {section, user} = getState();
let item = section.items.get(sid);
// 接口请求跳出的条件:
// 前置条件:下拉刷新优先级高于上拉加载
... ... @@ -137,39 +142,39 @@ export function newPost(ptr = false) {
// 1.当次请求不是下拉刷新,同时正在进行下拉刷新的请求,跳出
// 2.当次请求不是下拉刷新,同时接口请求正在加载中, 跳出
// 3.当次请求不是下拉刷新,数据已全部加载完成,跳出
if (section.ptr || section.new.isFetching || section.new.endReached) {
if (item.ptr || item.new.isFetching || item.new.endReached) {
return;
}
}
dispatch(newPostRequest(ptr));
dispatch(newPostRequest(sid, ptr));
let uid = user.profile.uid;
let forumCode = section.id;
let forumCode = item.id;
let lastedTime = 0;
if (!ptr) {
lastedTime = section.new.lastedTime;
lastedTime = item.new.lastedTime;
}
let limit = 10;
return new SectionService().newPost(uid, lastedTime, forumCode, limit)
.then(json => {
let payload = parseNewPost(json);
if (!ptr) {
let oldList = section.new.list.toJS();
let oldList = item.new.list.toJS();
let list = [...oldList, ...payload.list];
payload.list = list;
}
dispatch(newPostSuccess(payload));
dispatch(newPostSuccess(sid, payload));
})
.catch(error => {
dispatch(newPostFailure(error));
dispatch(newPostFailure(sid, error));
});
};
}
export function hotPost(ptr = false) {
export function hotPost(sid, ptr = false) {
return (dispatch, getState) => {
let {section, user} = getState();
let item = section.items.get(sid);
// 接口请求跳出的条件:
// 前置条件:下拉刷新优先级高于上拉加载
if (ptr) {
... ... @@ -178,45 +183,46 @@ export function hotPost(ptr = false) {
// 1.当次请求不是下拉刷新,同时正在进行下拉刷新的请求,跳出
// 2.当次请求不是下拉刷新,同时接口请求正在加载中, 跳出
// 3.当次请求不是下拉刷新,数据已全部加载完成,跳出
if (section.ptr || section.hot.isFetching || section.hot.endReached) {
if (item.ptr || item.hot.isFetching || item.hot.endReached) {
return;
}
}
dispatch(hotPostRequest(ptr));
dispatch(hotPostRequest(sid, ptr));
let uid = user.profile.uid;
let forumCode = section.id;
let forumCode = item.id;
let lastedTime = 0;
if (!ptr) {
lastedTime = section.hot.lastedTime;
lastedTime = item.hot.lastedTime;
}
let limit = 10;
return new SectionService().hotPost(uid, lastedTime, forumCode, limit)
.then(json => {
let payload = parseNewPost(json);
if (!ptr) {
let oldList = section.hot.list.toJS();
let oldList = item.hot.list.toJS();
let list = [...oldList, ...payload.list];
payload.list = list;
}
dispatch(hotPostSuccess(payload));
dispatch(hotPostSuccess(sid, payload));
})
.catch(error => {
dispatch(hotPostFailure(error));
dispatch(hotPostFailure(sid, error));
});
};
}
export function setActiveTab(tab) {
export function setActiveTab(sid, tab) {
return {
type: SECTION_SET_ACTIVE_TAB,
payload: tab,
payload: {sid, tab},
};
}
export function sectionClean() {
export function sectionClean(sid) {
return {
type: SECTION_CLEAN,
payload: sid,
};
}
... ...
... ... @@ -7,14 +7,14 @@
/**
* ## Import immutable record
*/
import {Record, List, Map} from 'immutable';
import {Record, List, Map, Stack} from 'immutable';
/**
* ## InitialState
*
* The fields we're concerned with
*/
let InitialState = Record({
let item = new (Record({
isFetching: false,
error: null,
id: 0,
... ... @@ -47,6 +47,12 @@ let InitialState = Record({
list: List(),
endReached: false,
})),
}));
let InitialState = Record({
sid: -1,
items: List(),
item: item,
});
export default InitialState;
... ...
... ... @@ -45,16 +45,35 @@ export default function sectionReducer(state = initialState, action) {
switch (action.type) {
case GO_TO_SECTION: {
let sid = state.sid + 1;
// 获取新的初始状态item
let item = initialState.item;
// 设置item的value
item = item.set('id', action.payload.id)
.set('name', action.payload.name);
// items新增item
let newItems = state.items.push(item);
let nextState = state.set('sid', sid)
.set('items', newItems);
return nextState;
}
case SECTION_HEADER_REQUEST: {
let nextState = state.set('isFetching', true)
.set('error', null);
let sid = action.payload;
let nextState = state.setIn(['items', sid, 'isFetching'], true)
.setIn(['items', sid, 'error'], null)
.setIn(['items', sid, 'ptr'], true);
return nextState;
}
case SECTION_HEADER_SUCCESS: {
let {notice, header} = action.payload;
let nextState = state.set('isFetching', false)
let {sid, json} = action.payload;
let {notice, header} = json;
let item = state.items.get(sid);
item = item.set('isFetching', false)
.set('error', null)
.set('ptr', false)
.setIn(['header', 'uri'], header.uri)
.setIn(['header', 'title'], header.title)
.setIn(['header', 'post'], header.post)
... ... @@ -63,67 +82,79 @@ export default function sectionReducer(state = initialState, action) {
.setIn(['notice', 'duration'], notice.duration)
.setIn(['notice', 'open'], notice.open)
.setIn(['notice', 'list'], Immutable.fromJS(notice.list));
let nextState = state.setIn(['items', sid], item);
return nextState;
}
case SECTION_HEADER_FAILURE: {
let nextState = state.set('isFetching', false)
.set('error', action.payload);
let {sid, error} = action.payload;
let nextState = state.setIn(['items', sid, 'isFetching'], false)
.setIn(['items', sid, 'error'], error)
.setIn(['items', sid, 'ptr'], false);
return nextState;
}
case SECTION_HOT_POST_REQUEST: {
let nextState = state.setIn(['hot', 'isFetching'], true)
.setIn(['hot', 'error'], null)
.set('ptr', action.payload);
let {sid, ptr} = action.payload;
let nextState = state.setIn(['items', sid, 'hot', 'isFetching'], true)
.setIn(['items', sid, 'hot', 'error'], null);
return nextState;
}
case SECTION_HOT_POST_SUCCESS: {
let {lastedTime, list, endReached} = action.payload;
let nextState = state.setIn(['hot', 'isFetching'], false)
let {sid, json} = action.payload;
let {lastedTime, list, endReached} = json;
let item = state.items.get(sid);
item = item.setIn(['hot', 'isFetching'], false)
.setIn(['hot', 'error'], null)
.setIn(['hot', 'lastedTime'], lastedTime)
.setIn(['hot', 'endReached'], endReached)
.setIn(['hot', 'list'], Immutable.fromJS(list));
let nextState = state.setIn(['items', sid], item);
return nextState;
}
case SECTION_HOT_POST_FAILURE: {
let nextState = state.setIn(['hot', 'isFetching'], false)
.setIn(['hot', 'error'], action.payload);
let {sid, error} = action.payload;
let nextState = state.setIn(['items', sid, 'hot', 'isFetching'], false)
.setIn(['items', sid, 'hot', 'error'], error);
return nextState;
}
case SECTION_NEW_POST_REQUEST: {
let nextState = state.setIn(['new', 'isFetching'], true)
.setIn(['new', 'error'], null)
.set('ptr', action.payload);
let {sid, ptr} = action.payload;
let nextState = state.setIn(['items', sid, 'new', 'isFetching'], true)
.setIn(['items', sid, 'new', 'error'], null);
return nextState;
}
case SECTION_NEW_POST_SUCCESS: {
let {lastedTime, list, endReached} = action.payload;
let nextState = state.setIn(['new', 'isFetching'], false)
let {sid, json} = action.payload;
let {lastedTime, list, endReached} = json;
let item = state.items.get(sid);
item = item.setIn(['new', 'isFetching'], false)
.setIn(['new', 'error'], null)
.setIn(['new', 'lastedTime'], lastedTime)
.setIn(['new', 'endReached'], endReached)
.setIn(['new', 'list'], Immutable.fromJS(list));
let nextState = state.setIn(['items', sid], item);
return nextState;
}
case SECTION_NEW_POST_FAILURE: {
let nextState = state.setIn(['new', 'isFetching'], false)
.setIn(['new', 'error'], action.payload);
let {sid, error} = action.payload;
let nextState = state.setIn(['items', sid, 'new', 'isFetching'], false)
.setIn(['items', sid, 'new', 'error'], error);
return nextState;
}
case SECTION_SET_ACTIVE_TAB:
return state.set('activeTab', action.payload);
case GO_TO_SECTION:
return state.set('id', action.payload.id)
.set('name', action.payload.name);
case SECTION_SET_ACTIVE_TAB: {
let {sid, tab} = action.payload;
let item = state.items.get(sid);
item = item.set('activeTab', tab);
let nextState = state.setIn(['items', sid], item);
return nextState;
}
case POST_LIKE_REQUEST: {
return newLikeState(state, action.payload, true);
... ... @@ -133,8 +164,15 @@ export default function sectionReducer(state = initialState, action) {
return newLikeState(state, action.payload, false);
}
case SECTION_CLEAN:
return initialState;
case SECTION_CLEAN: {
let sid = action.payload;
if (state.items.size > sid) {
let items = state.items.pop();
let nextState = state.set('sid', sid - 1)
.set('items', items);
return nextState;
}
}
}
return state;
... ... @@ -163,10 +201,15 @@ function newLikeState(state, postId, like) {
return nextList;
};
let hotList = likeState(state.hot.list, postId, like);
let newList = likeState(state.new.list, postId, like);
let nextState = state;
state.items.map((item, i) => {
let hotList = likeState(item.hot.list, postId, like);
let newList = likeState(item.new.list, postId, like);
item = item.setIn(['hot', 'list'], hotList)
.setIn(['new', 'list'], newList);
nextState = nextState.setIn(['items', i], item);
});
let nextState = state.setIn(['hot', 'list'], hotList)
.setIn(['new', 'list'], newList);
return nextState;
}
... ...