Как решить реагировать с использованием бесконечной прокрутки загрузки данных вызвать проблему бесконечного цикла - PullRequest
0 голосов
/ 09 июня 2019

Привет всем, я создаю сторонний проект через youtube v3 api

На основе практики и по какой-то причине я должен использовать старую версию реагировать + редукс для завершения этого побочного проекта

Реакция: v16.4.2 Redux: v5.0.7

UI lib Antd: v3.10.9 Styled-компоненты: v3.4.6

На странице поиска я хочу использовать ленивую загрузку с помощью "Infinite"Прокрутите ".

Так что я" реагирую-бесконечный скроллер "этого комплекта, когда прокручиваю близко к основанию, повторно вызываю 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;
    }
}


Теперь после входа на страницу поиска, реакция будет продолжать setState и привести к ошибке.Я не знаю, как управлять "this.state.searchStatus" недели "componentDidUpdate".Эта проблема.

Пожалуйста, помогите мне, я благодарен !!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...