簡體   English   中英

用於無限滾動的 React JS 地圖數組

[英]React JS map array for infinite scroll

我有一個簡單的 React 應用程序,我在其中獲取 Flickr Public Feed API 並顯示它。 不幸的是,它多次映射數組,在那里我可以看到重復的照片。 該請求總是返回一個包含 20 個具有相同圖片的項目的數組,解釋重復。

檢查下面的代碼:

import React, { Component } from 'react';
import $ from 'jquery';

import PhotoListItem from '../../components/photoListItem';
import Searchbar from '../../components/searchBar';
import ScrollButton from '../../components/scrollButton';

import '../app/index.css';

export default class PhotoApp extends Component {
    constructor(props) {
        super(props);

        this.state = {
            photoList: [],
            searchTerm: 'cyanotype',
            items: 10,
            loadingState: false,
        }
    }

    componentDidMount() {
        this.getPhotoList();
        this.onInfiniteScroll();
    }

    /* get data from Flickr public feed */
    getPhotoList = () => {
        const flickrApiPoint = "https://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?&tags=" + this.state.searchTerm;

        try {
            $.ajax({
                url: flickrApiPoint,
                dataType: 'jsonp',
                data: { format: "json" },
                success: function (data) {
                    this.setState({ photoList: data.items });
                }.bind(this)
            });
        }
        catch (err) {
            console.log(err);
        }
    }

    /* code for infinite scroll */
    onInfiniteScroll = () => {
        this.refs.iScroll.addEventListener("scroll", () => {
            if (this.refs.iScroll.scrollTop + this.refs.iScroll.clientHeight >= this.refs.iScroll.scrollHeight - 20) {
                this.loadMoreItems();
            }
        });
    }

    /*  */
    displayItems = () => {
        var items = [];
        for (var i = 0; i < this.state.items; i++) {
            items.push(
                this.state.photoList.map((photo, index) => {
                    const author = photo.author.split(/"/)[1];
                    const authorLink = photo.description.split(/"/)[1]
                    const description = photo.description.split(/"/)[13]
                    return (
                        <PhotoListItem
                            key={index}
                            url={photo.media.m}
                            photoLink={photo.link}
                            title={photo.title}
                            author={author}
                            authorLink={authorLink}
                            description={description}
                            tags={photo.tags} />
                    )
                })
            );
        }
        return items;
    }

    /*  */
    loadMoreItems = () => {
        if (this.state.loadingState) {
            return;
        }
        this.setState({ loadingState: true });
        setTimeout(() => {
            this.setState({ items: this.state.items + 10, loadingState: false });
        }, 1000);
    }

    render() {
        return (
            <div className='appContainer' ref="iScroll">
                <div className='appHeader'>
                    <h1 className='headerTitle'>Welcome to Flickr Alternative Photography Feed!</h1>
                </div>

                <div className='gridContainer'>
                    {this.displayItems()}
                </div>
                {this.state.loadingState ? <p className='loading'>Loading items...</p> : ""}
            </div>
        );
    }
}

這是現場示例

問題是圍繞this.displayItems() ,但我該如何解決這個問題? 任何幫助表示贊賞。 謝謝!

您可以通過按照您想要在 JSX 中顯示的項目數量對數組進行切片來實現這一點:

this.state.photoList.slice(0, this.state.items).map(

然后,您將不得不使用setState的回調版本來使用您的狀態的舊值並增加您想要顯示的內容:

this.setState(old => ({ items: old.items + 2, loadingState: false }));

全功能示例(建議使用“整頁”選項):

 class PhotoListItem extends React.Component { render() { return ( <div className="image-card"> <img className="image-card__image" alt="" src={this.props.url} /> <div className="image-card__body"> <div className="image-title"> <a href={this.props.photoLink}>{this.props.title}</a> <span className="image-author"> {" "} by <a href={this.props.authorLink}>{this.props.author}</a> </span> </div> <div className="image-description"> <span className="description">Description:</span>{" "} {this.props.description} </div> <div className="image-tags"> <span className="tags">Tags:</span> {this.props.tags} </div> </div> </div> ); } } class PhotoApp extends React.Component { constructor(props) { super(props); this.state = { photoList: [], items: 2, searchTerm: "cyanotype", loadingState: false }; } componentDidMount() { this.getPhotoList(); this.onInfiniteScroll(); } /* get data from Flickr public feed */ getPhotoList = () => { const flickrApiPoint = "https://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?&tags=" + this.state.searchTerm; try { $.ajax({ url: flickrApiPoint, dataType: "jsonp", data: { format: "json" }, success: function(data) { this.setState({ photoList: data.items }); }.bind(this) }); } catch (err) { console.log(err); } }; /* code for infinite scroll */ onInfiniteScroll = () => { this.refs.iScroll.addEventListener("scroll", () => { if ( this.refs.iScroll.scrollTop + this.refs.iScroll.clientHeight >= this.refs.iScroll.scrollHeight - 20 ) { this.loadMoreItems(); } }); }; /* */ loadMoreItems = () => { if (this.state.loadingState) { return; } this.setState({ loadingState: true }); setTimeout(() => { this.setState(old => ({ items: old.items + 2, loadingState: false })); }, 1000); this.getPhotoList(); }; render() { return ( <div className="appContainer" ref="iScroll"> <div className="appHeader"> <h1 className="headerTitle"> Welcome to Flickr Alternative Photography Feed! </h1> </div> <div className="gridContainer"> {this.state.photoList.slice(0, this.state.items).map((photo, index) => { const author = photo.author.split(/"/)[1]; const authorLink = photo.description.split(/"/)[1]; const description = photo.description.split(/"/)[13]; return ( <PhotoListItem key={index} url={photo.media.m} photoLink={photo.link} title={photo.title} author={author} authorLink={authorLink} description={description} tags={photo.tags} /> ); })} </div> {this.state.loadingState ? ( <p className="loading">Loading items...</p> ) : ( "" )} </div> ); } } ReactDOM.render(<PhotoApp />, document.getElementById("root"));
 body, html { margin: 0; min-height: 100%; } .appContainer { font-family: "Helvetica", sans-serif; width: 100%; height: 100vh; overflow: auto; } .appHeader { text-align: center; background-color: #033666; padding: 1rem; } .headerTitle { color: #fff; } .gridContainer { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); padding: 1rem; grid-gap: 1rem 1rem; } .loading { text-align: center; color: #033666; } @media only screen and (max-width: 320px) { .appHeader>h1 { font-size: 1.2rem; } } a, a:visited { color: #000; text-decoration: none; } a:hover { color: #033666; text-decoration: underline; } .image-card { display: flex; display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; flex-direction: column; width: auto; height: auto; margin: .5rem; border-radius: 5px; box-shadow: 0 5px 15px rgba(0, 0, 0, .15); background: #fff; } .image-card__image { border-radius: 5px 5px 0 0; width: 100%; height: 200px; object-fit: cover; } .image-card__body { padding: .5rem 1rem 1rem; } .image-title { font-weight: 600; margin: 0; word-wrap: break-word; padding-bottom: .7rem; cursor: pointer; } .image-author { font-weight: 100; font-size: .8rem; cursor: pointer; } .image-owner { margin-top: 0; font-size: .8rem; } .image-date-view-wrapper { display: flex; align-items: center; justify-content: space-between; } .image-description { padding-bottom: .7rem; font-size: .9rem; word-wrap: break-word; } .tags, .description { font-weight: 600; } .image-tags { font-size: .8rem; word-wrap: break-word; } .App { font-family: sans-serif; text-align: center; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.0/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.1/umd/react-dom.production.min.js"></script> <div id="root" />

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM