reactjs - React Native Flatlist 使用 redux 获得无限循环 onEndReached
问题描述
我正在使用 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;
解决方案
您基本上需要一种方法来停止调度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
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.
推荐阅读
- html - 未捕获的 ReferenceError:未定义 sceditor
- git - 从工作树中拉出?
- python - 发送输入后立即删除输入行
- xslt-1.0 - 使用 XSLT1 将文档动态指定到变量中
- scala - 在 AWS Glue 上使用 Deequ
- typescript - 混合手动声明和推断类型
- java - 用于验证 Dto 的 Csutom 注释包含两个使用 java 验证和 Spring Boot 的列表
- c# - Mailkit 以编程方式连接到 Office365
- kubernetes - 为什么匹配的持久卷不绑定到匹配的持久卷声明(使用 k3s)?
- google-cloud-platform - 如何使用大查询导出数据语句创建文件名中包含日期的文件