FlatList onEndReached вызывается несколько раз - PullRequest
0 голосов
/ 21 ноября 2018

Я делаю собственный нативный проект, в котором пользователь может искать изображения с помощью Flickr API. Все остальное работает нормально, но у меня возникла проблема при реализации нумерации страниц.Я использовал FlatList onEndReached, чтобы определить, когда пользователь прокручивал список до конца в списке, но проблема в том, что onEndReached вызывается несколько раз (включая один во время первого рендеринга).Я даже отключил отказов, как сказал здесь , но он все еще вызывается более одного раза

 export default class BrowserHome extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      isLoading: false,
      tagParam: "cat",
      pageNum: -1,
      data: [],
      photosObj: ""
    };
  }

  componentDidMount() {
    this.setState({
      isLoading: true
    });
    try {
      this.makeRequest();
    } catch {
      console.log("error has occurred");
    }
  }

  makeRequest = () => {
    const { tagParam, pageNum } = this.state;
    let url = `https://api.flickr.com/services/rest/? 
               method=flickr.photos.search
               &api_key=${apiKey}&format=json&tags=${tagParam}
               &per_page=30&page=${pageNum + 1}&nojsoncallback=1`;
    fetch(url, {
      method: "GET"
    })
      .then(response => response.json())
      .then(responseJSON => {
        this.setState({
          data: this.state.data.concat(responseJSON.photos.photo),
          isLoading: false,
          pageNum: responseJSON.photos.page
        });
      })
      .catch(error => {
        console.log(error);
        this.setState({ isLoading: false });
        throw error;
      });
  };

  render() {
    if (this.state.isLoading) {
      return <ActivityIndicator animating={true} size="large" />;
    }

    return (
      <View
        style={{
          flex: 1,
          height: 200,
          justifyContent: "flex-start",
          width: screenSize.width,
          backgroundColor: "black"
        }}
      >
        <Text>This is browserhome</Text>
        <FlatList
          style={{
            width: screenSize.width
          }}
          numColumns={3}
          data={this.state.data}
          keyExtractor={item => item.id}
          bounces={false}
          onEndReachedThreshold={1}
          onEndReached={({ distanceFromEnd }) => {
            this.loadMoreItem();
            alert("end reached call");
          }}
          renderItem={({ item, index }) => (
            <>
              <ImageTile imageURL={this.createImageURL(item)} />
            //  <Text style={{ color: "white" }}>
             //   {index}
             //   {console.log(index)}
             // </Text>
            </>
          )}
        />
      </View>
    );
  }

  createImageURL(item) {
    let server = item.server,
      id = item.id,
      secret = item.secret;
    let urlString = `https://farm${
      item.farm
    }.staticflickr.com/${server}/${id}_${secret}_s.jpg`;
    return urlString;
  }

  loadMoreItem() {
    this.makeRequest();
  }
}

Ответы [ 3 ]

0 голосов
/ 22 марта 2019

Вот как я решил свою проблему:

Вот мое начальное состояние:

state = {
  onEndReachedCalledDuringMomentum: true,
  lastLoadCount: 0,
}

Это мой FlatList

<FlatList
   keyboardShouldPersistTaps="always"
   style={...}
   data={this.state.searchResults}
   extraData={this.state}
   bounces={false}
   renderItem={({ item, index }) =>
         <SearchResultView
            uriSsource={item.image}
            itemIndex={index}
            name={item.name}
          />
   }
   showsVerticalScrollIndicator={false}
   keyExtractor={this._keyExtractor}
   numColumns={2}
   onEndReached={() => this._loadMoreData()}
   onEndReachedThreshold={0.01}
   ListFooterComponent={this._renderSearchResultsFooter}
   onMomentumScrollBegin={() => this._onMomentumScrollBegin()}
/>

Вот функции, которые я вызываю:

// Key Extractor
    _keyExtractor = (item, index) => item.id;
// Check if list has started scrolling
    _onMomentumScrollBegin = () => this.setState({ onEndReachedCalledDuringMomentum: false });
// Load more data function
    _loadMoreData = () => {
            if (!this.state.onEndReachedCalledDuringMomentum) {
                this.setState({ onEndReachedCalledDuringMomentum: true }, () => {

                    setTimeout(() => {
                        if (this.state.lastLoadCount >= 20 && this.state.notFinalLoad) {
                            this.setState({

                                page: this.state.page + 1,
                            }, () => {
                                // Then we fetch more data;
                                this._callTheAPIToFetchMoreData();
                            });
                        };
                    }, 1500);
                });
            };
        };
// Show your spinner
    _renderSearchResultsFooter = () => {
            return (
                (this.state.onEndReachedCalledDuringMomentum && this.state.lastLoadCount >= 20 && this.state.notFinalLoad) ?
                    <View style={{ marginBottom: 30, marginTop: -50, alignItems: 'center' }}>
                        <ActivityIndicator size="large" color="#e83628" />
                    </View> : null
            )
        }

Как только я получаю данные, внутри _callTheAPIToFetchMoreData() я обновляю состояние следующим образом:

this.setState({
  lastLoadCount: results.length,
  onEndReachedCalledDuringMomentum: results.length >= 20 ? true : false,
  notFinalLoad: results.length >= 20 ? true : false
}

Счастливого кодирования.

0 голосов
/ 31 июля 2019

onEndReached вызывается много раз, вместо этого используйте onMomentumScrollEnd для загрузки отложенных данных.

<FlatList
  data={data}
  keyExtractor={item => item.uid}
  onMomentumScrollEnd={retrieveData}
  onEndReachedThreshold={0}
/>
0 голосов
/ 21 ноября 2018

Вам просто нужно установить onEndReachedThreshold в качестве скорости видимой длины.Так что вам просто нужно установить его как число, меньшее 1. Например, НОЛЬ или 0.5, тогда он должен работать !!!!!

Дайте мне знать, сработало ли это для вас.

...