如何通过按底部栏选项卡刷新 FlatList?

问题描述 投票:0回答:2

按下底部栏选项卡并且我们位于 FlatList 的顶部时,我无法找到刷新 FlatList 的正确方法。

我确实使用

useScrollToTop
成功到达了FlatList的顶部,我也设法重新获取数据,但它不是我想要的。

import { useScrollToTop } from '@react-navigation/native';

const flatlistRef = useRef<FlatList>(null);
useScrollToTop(flatlistRef);

这会滚动到 FlatList 的顶部,但是:

  1. 仅当按下底部栏选项卡时已到达顶部时,我才想重新获取
  2. 使用这个我没有刷新控制动画来看到某些东西正在重新获取(它只是在地下重新获取)

我正在使用 React-Navigation 作为底部选项卡 (

"@react-navigation/bottom-tabs": "^6.5.16"
)

有什么想法吗?

谢谢

react-native react-navigation react-native-flatlist react-navigation-bottom-tab
2个回答
0
投票

找到了解决方案 - 可能是更好的答案,如果可以随时回复!

const [isRefreshing, setIsRefreshing] = useState<boolean>(false);
const flatlistRef = useRef<FlatList>(null);
const scrollPositionRef = useRef(0);

const refetchControl = async () => {
    setIsRefreshing(true);
    await refetchAPIEndpoint();
    setIsRefreshing(false);
};

const handleScroll = (event: NativeSyntheticEvent<NativeScrollEvent>) => {
    scrollPositionRef.current = event.nativeEvent.contentOffset.y;
};

const scrollToTop = async () => {
    if (scrollPositionRef.current === 0) {
        await refetchControl();
        flatlistRef.current?.scrollToOffset({ offset: 0 });
    } else {
        flatlistRef.current?.scrollToOffset({ offset: 0 });
    }
}

useScrollToTop(
    useRef({ scrollToTop }),
);

return (
    <FlatList
        ...
        ref={flatlistRef}
        onScroll={handleScroll}
        refreshControl={<RefreshControl refreshing={isRefreshing} onRefresh={refetchControl} />}
    />
);

不太明白

useScrollToTop(useRef({ scrollToTop }))
这个,但它有效 - 请随意解释!


0
投票

由于您想要做的不仅仅是在选项卡聚焦时滚动到顶部,因此您应该放弃使用

useScrollToTop
,而只使用 useFocusEffect。每当当前选项卡成为焦点时就会调用该钩子。您可以在此挂钩中刷新数据并滚动到平面列表的顶部(demo):

import { useState, useEffect, useCallback, useRef } from 'react';
import {
  View,
  Text,
  StyleSheet,
  FlatList,
  ActivityIndicator,
} from 'react-native';
import { useFocusEffect } from '@react-navigation/native';
import useCountSeconds from './useCountSeconds';
import ListItem from './ListItem';

export default function HomeScreen({ navigation }) {
  const [data, setData] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const flatlistRef = useRef();
  // debug value used to show when last fetch was made
  const [lastRefresh, setLastRefresh] = useState(Date.now());
  // counts seconds between lastRefresh and current time
  const seconds = useCountSeconds(lastRefresh);
  const refreshData = useCallback(async () => {
    setIsLoading(true);
    try {
      // get sample data
      const data = await fetch('https://dummyjson.com/products');
      const json = await data.json();
      setData(json.products);
      // update lastRefresh
      setLastRefresh(Date.now());
      setIsLoading(false);
    } catch (err) {
      console.log(err);
      setIsLoading(false);
    }
  }, []);

  useFocusEffect(
    // must wrap function in callback to avoid
    // calling this effect alot
    useCallback(() => {
      console.log('Home screen focused');
      refreshData();
      flatlistRef.current?.scrollToOffset({ offset: 0 });
    }, [refreshData])
  );

  return (
    <View style={styles.container}>
      {isLoading && <ActivityIndicator size="large" />}
      <Text>Refreshed: {seconds}s ago</Text>
      <View style={styles.listContainer}>
        <FlatList
          ref={flatlistRef}
          data={data}
          renderItem={(props) => <ListItem {...props} />}
          keyExtractor={(item) => item.id}
          numColumns={2}
        />
      </View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    alignItems: 'center',
    justigyContent: 'center',
  },
  listContainer: {
    flex: 1,
    margin: 10,
    padding: 5,
  },
});
© www.soinside.com 2019 - 2024. All rights reserved.