大家好,我正在通过youtube v3 api创建辅助项目
基于实践,由于某种原因,我必须使用旧版本的react + redux来完成此附带项目
反应:v16.4.2 Redux:v5.0.7
UI库 蚂蚁:v3.10.9 样式组件:v3.4.6
在搜索页面中,我想对“无限滚动”使用延迟加载。
所以我“ react-infinite-scroller”这个工具包,当滚动到底部时,重新调用api并执行setState以达到重新渲染的效果。
但是我发现当前执行重新渲染的方法是通过生命周期,getDerivedStateFromProps和componentDidUpdate 导致无限循环问题
因为加载新项目时,它将触发滚动条调用api的条件,以便屏幕进入setState的无限循环问题。希望您能提供帮助。
查看组件
import React, {Component} from 'react';
import PropTypes from 'prop-types';
import InfiniteScroll from 'react-infinite-scroller';
import styled from 'styled-components';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {PortalRedux, SearchRedux} from '../../Redux/Modules';
import {Header} from '../../Components/Layout';
import {VideoListPlayItem, ListDropdown} from '../../Components/Modules';
import {formatData} from '../../Common/BasicService';
import {googleApiKey} from '../../ApiCenter/Api/Api';
import * as ComponentConfig from '../../Common/ComponentConfig';
import * as Style from '../../Common/Style';
const SearchView = styled.div`
width: 100%;
height: 90vh;
`;
const SearchContent = styled.div`
width: 100%;
height: 100%;
padding: 2% 0;
display: flex;
flex-wrap: wrap;
justify-content: center;
`;
const AdvancedSearch = styled.div`
height: 4vh;
minHeight: 60px;
`;
const infiniteScrollDomStyle = {
width: '100%',
height: '90vh',
padding: '0 8%',
overflow: 'auto'
};
const btnConfig = {
color: `${Style.FontStressColor}`,
border: 0,
marginLeft: 8
};
const VideoListPlayItemConfig = {
width: '100%',
marginBottom: '2rem',
displayWidth: 320,
playerConfig: {
width: '320px',
height: '180px',
defaultControls: false,
showControl: false,
defaultPlay: true,
mute: true
},
playerInlineConfig: {
minWidth: '600px',
minHeight: '18px'
}
};
class Search extends Component {
constructor(props) {
super(props);
this.state = {
searchStatus: false,
searchKey: '',
nextPageToken: '',
searchResult: [],
};
}
static getDerivedStateFromProps(nextProps) {
switch (nextProps.action.type) {
case SearchRedux.SearchActions.getSearchSuccess:
return {
searchStatus: true,
searchKey: action.payload.config.params.q,
nextPageToken: nextProps.action.payload.nextPageToken,
searchResult: nextProps.action.payload.items
};
default:
break;
}
return null;
}
componentDidUpdate(nextProps) {
// If you use this.setState to refresh data, this will result in an infinite loop.
if (this.state.searchStatus) {
this.setState({
searchStatus: false,
searchKey: action.payload.config.params.q,
nextPageToken: nextProps.action.payload.nextPageToken,
searchResult: nextProps.action.payload.items
});
}
}
getNextLoadSearchData = () => {
const request = {
part: 'snippet',
maxResults: 10,
q: this.state.searchKey,
type: 'video',
pageToken: this.state.nextPageToken,
key: googleApiKey
};
this.props.SearchActionsCreator.getSearchResultData(request);
};
render() {
return (
<div>
<Header/>
<SearchView>
<AdvancedSearch>
<ListDropdown
configData={ComponentConfig.DateSearchDropdown}
btnConfig={btnConfig}
itemClickAction={this.props.PortalActionsCreator.changeToPage}
/>
<ListDropdown
configData={ComponentConfig.TypeSearchDropdown}
btnConfig={btnConfig}
itemClickAction={this.props.PortalActionsCreator.changeToPage}
/>
</AdvancedSearch>
<div style={infiniteScrollDomStyle} ref={(ref) => this.scrollParentRef = ref}>
<InfiniteScroll
threshold={250}
hasMore={true}
initialLoad={false}
isReverse={false}
useWindow={true}
loadMore={this.getNextLoadSearchData}
getScrollParent={() => this.scrollParentRef}
>
<SearchContent>
{
this.state.searchResult.length !== 0
? formatData.videoListPlayItemRespond(this.state.searchResult).map((item) => {
return (
<VideoListPlayItem
key={item.id}
VideoListPlayItemConfig={VideoListPlayItemConfig}
VideoListPlayItemData={
{
title: item.title,
description: item.description,
playData: item.playData,
thumbnailURL: item.imgURL
}
}
/>
);
})
: <div>No-Data</div>
}
</SearchContent>
</InfiniteScroll>
</div>
</SearchView>
</div>
);
}
}
Search.propTypes = {
PortalActionsCreator: PropTypes.object.isRequired,
SearchActionsCreator: PropTypes.object.isRequired,
};
export default connect(
(state) => {
return {action: state.SearchReducer.action};
},
(dispatch) => {
return {
PortalActionsCreator: bindActionCreators(PortalRedux.PortalActionsCreator, dispatch),
SearchActionsCreator: bindActionCreators(SearchRedux.SearchActionsCreator, dispatch),
};
}
)(Search);
Redux
import {createAction} from 'redux-actions';
import {callApi} from '../../../ApiCenter/Api/CallApi';
import * as apiData from '../../../ApiCenter/Api/Api';
export const SearchActions = {
getSearchStart: 'GET_SEARCH_START',
getSearchSuccess: 'GET_SEARCH_SUCCESS',
getSearchFailed: 'GET_SEARCH_FAILED',
};
const getSearchResultData = (request) => {
return (dispatch) => {
dispatch(createAction(SearchActions.getSearchStart)());
callApi.get(apiData.searchURL, request)
.then((respond) => {
dispatch(createAction(SearchActions.getSearchSuccess(request))(respond));
})
.catch((error) => {
dispatch(createAction(SearchActions.getSearchFailed)(error));
});
};
};
export const SearchActionsCreator = {
getSearchResultData,
};
export default function SearchReducer(state = {action: ''}, action) {
switch (action.type) {
case SearchActions.getSearchSuccess:
case SearchActions.getSearchFailed:
return {action: action};
default:
return state;
}
}
现在,进入搜索页面后,react将继续进入setState并呈现为错误。我不知道如何控制“ componentDidUpdate”周的“ this.state.searchStatus”。这个问题。
请帮助我,我很感激!