简体   繁体   English

React Native Flatlist 使用 redux 获得无限循环 onEndReached

[英]React Native Flatlist gets endless loop onEndReached using redux

I am using react-native FlatList component to render a list.我正在使用 react-native FlatList 组件来呈现列表。 Im fetching dummy data from an action but my pagination is not acting as expected, it's rendering everything instantly when I'm using onEndReached.我从一个动作中获取虚拟数据,但我的分页没有按预期运行,当我使用 onEndReached 时,它会立即渲染所有内容。

what am i missing?我错过了什么?

check my expo https://snack.expo.io/@thesvarta/19d294检查我的 expo https://snack.expo.io/@thesvarta/19d294

so here are my actions所以这是我的行动

  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,
    });
  };
};

My reducers我的减速机

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;
  }
};

My component我的组件

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;

You basically need a way to stop dispatching the loadMoreFeed action.您基本上需要一种方法来停止调度loadMoreFeed操作。 This is the reason almost all server-sided paginations include either the next page number or the total number of pages.这就是几乎所有服务器端分页都包含下一页编号或总页数的原因。

I have added a simple page number check on your action:我在您的操作中添加了一个简单的页码检查:

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,
  });
}

I have edited your snack with the fix, and you can find it at this link: https://snack.expo.io/rJmsZu0iS我已经用修复编辑了你的零食,你可以在这个链接找到它: https://snack.expo.io/rJmsZu0iS

Again, this is just a very simple method of keeping track of the number of pages.同样,这只是一种非常简单的跟踪页数的方法。 You would probably want to change it in production.您可能希望在生产中更改它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM