[英]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.