React Native Flatlist使用Redux在onEndReached上获得无限循环

时间:2019-11-17 03:37:50

标签: reactjs react-native redux react-redux react-native-flatlist

我正在使用react-native FlatList组件来呈现列表。我正在从操作中获取伪数据,但是我的分页操作不符合预期,当我使用onEndReached时,它会立即呈现所有内容。

我想念什么?

检查我的博览会 https://snack.expo.io/@thesvarta/19d294

这是我的动作

  import { FETCH_FEED, MORE_FEED, REFRESH_FEED } from './actionTypes';

export const fetchFeed = () => {
  return async (dispatch, getState) => {
    const url = 'https://reqres.in/api/users?page=' + 1;
    const response = await fetch(url, {
      method: 'GET',
    });
    if (!response.ok) {
      const errorResData = await response.json();
      let message = 'error';
      throw new Error(message);
    }
    const resData = await response.json();
    dispatch({
      type: FETCH_FEED,
      data: resData.data,
      page: 1,
      rows: 1,
      message: resData.MESSAGE,
    });
  };
};
export const fetchRefreshFeed = () => {
  return async (dispatch, getState) => {
    const url = 'https://reqres.in/api/users?page=' + 1;
    const response = await fetch(url, {
      method: 'GET',
    });
    if (!response.ok) {
      const errorResData = await response.json();
      let message = 'error';
      throw new Error(message);
    }
    const resData = await response.json();
    dispatch({
      type: REFRESH_FEED,
      refresh_data: resData.data,
      refresh_page: 1,
      refresh_rows: 1,
      refresh_message: resData.MESSAGE,
    });
  };
};
export const loadMoreFeed = page => {
  return async (dispatch, getState) => {
    const url = 'https://reqres.in/api/users?page=' + page;
    const response = await fetch(url, {
      method: 'GET',
    });
    if (!response.ok) {
      const errorResData = await response.json();
      let message = 'error';
      throw new Error(message);
    }
    const resData = await response.json();
    dispatch({
      type: MORE_FEED,
      more_data: resData.data,
      more_page: page,
      more_rows: 1,
      more_message: resData.MESSAGE,
    });
  };
};

我的减速器

import { FETCH_FEED, REFRESH_FEED, MORE_FEED } from '../actions/actionTypes';

const initialState = {
  data: [],
  error: null,
  page: 1,
  rows: 1,
  message: null,
};

export default (state = initialState, action) => {
  switch (action.type) {
    case FETCH_FEED:
      return {
        data: action.data,
        page: action.page,
        rows: action.rows,
        message: action.message,
      };
    case REFRESH_FEED:
      return {
        data: action.refresh_data,
        page: action.refresh_page,
        rows: action.refresh_rows,
      };
    case MORE_FEED:
      return {
        data: [...state.data, ...action.more_data],
        page: action.more_page,
        rows: action.more_rows,
      };
    default:
      return state;
  }
};

我的组件

import React, {
  useState,
  useEffect,
  useReducer,
  useCallback,
  getState,
} from 'react';
import { Navigation } from 'react-navigation';
import {
  StyleSheet,
  View,
  Text,
  StatusBar,
  TouchableHighlight,
  TouchableOpacity,
  FlatList,
  Image,
  Modal,
  Linking,
  ScrollView,
  Alert,
} from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import * as feedActions from '../../store/actions/feed';
const FeedScreen = props => {
  const [error, setError] = useState();
  const [refresh, setRefresh] = useState(false);
  const dispatch = useDispatch();
  const state = useSelector(state => state.feed);
  const loadFeed = useCallback(async () => {
    setError(null);
    try {
      await dispatch(feedActions.fetchFeed(state.page, state.rows));
    } catch (err) {
      setError(err.message);
    }
  }, [dispatch, setError]);

  useEffect(() => {
    loadFeed();
  }, [loadFeed]);
  const refreshFeed = useCallback(async () => {
    setError(null);
    setRefresh(true);
    try {
      await dispatch(feedActions.fetchRefreshFeed());
    } catch (err) {
      setError(err.message);
    }
    setRefresh(false);
  }, [dispatch, setError, setRefresh]);
  const morefeed = useCallback(async () => {
    setError(null);
    try {
      await dispatch(feedActions.loadMoreFeed(state.page + 1));
    } catch (err) {
      setError(err.message);
    }
  }, [dispatch, setError]);
  const renderRow = ({ item, index }) => {
    return (
      <View key={index}>
        <Text>{item.email}</Text>
      </View>
    );
  };
  if (error != null) {
    return (
      <View style={styles.centered}>
        <Text>An error occurred!</Text>
        <TouchableOpacity onPress={() => refreshFeed()}>
          Try again
        </TouchableOpacity>
      </View>
    );
  }
  return (
    <View style={styles.MainContainer}>
      <FlatList
        data={state.data}
        renderItem={renderRow}
        onRefresh={refreshFeed}
        refreshing={refresh}
        keyExtractor={(item, index) => index.toString()}
        onEndReached={morefeed}
        onEndReachedThreshold={0.5}
      />
    </View>
  );
};
const styles = StyleSheet.create({
  MainContainer: {
    flex: 1,
    backgroundColor: 'rgb(243,243,248)',
  },
});
export default FeedScreen;

1 个答案:

答案 0 :(得分:1)

您基本上需要一种方法来停止调度loadMoreFeed操作。这就是几乎所有服务器端分页都包括下一页号或总页数的原因。

我为您的操作添加了一个简单的页码检查:

if(page <= totalPages) {
  const url = 'https://reqres.in/api/users?page=' + page;
  const response = await fetch(url, {
    method: 'GET',
  });

  if (!response.ok) {
    const errorResData = await response.json();
    let message = 'error';
    throw new Error(message);
  }
  const resData = await response.json();
  dispatch({
    type: MORE_FEED,
    more_data: resData.data,
    more_page: page,
    more_rows: 1,
    totalPages: resData.total_pages,
    more_message: resData.MESSAGE,
  });
}

我已使用修复程序编辑了您的小吃,您可以在以下链接找到它:https://snack.expo.io/rJmsZu0iS

同样,这只是跟踪页面数的非常简单的方法。您可能要在生产中进行更改。