选项卡导航器内的 Flatlist 在 React Native 状态变化时滚动到顶部

Flatlist inside tab navigator is scrolling to top on state change in react native

Here you can see the gif

这是我的整个 Navigator 功能组件。我正在尝试使用 Tab Navigator 实现两个选项卡。一个显示加密货币,另一个显示外汇数据。

问题是,当我尝试在到达平面列表的末尾时加载更多数据时,平面列表滚动到顶部,因为我正在进行状态更改 [page+1]。

const Navigator = () => {    
  const Tab = createMaterialTopTabNavigator();

  const renderItems = ({ item }) => (
    <Text>{item.name}<Text>
  );  

  const fetchMarketData = async () => {
    console.log("Fetching");
    const marketData = await getCryptoMarketData({ page });
    if (marketData != "Network Error") {
      const ids = data.map((item) => item.id);
      let newData = marketData.filter((item) => !ids.includes(item.id));
      setData([...data, ...newData]);
      setFetching(false);
    } else {
      setFetching(false);
      Alert.alert(marketData, "Sorry for the inconvenience");
    }
  };

  useEffect(() => {
    setFetching(true);
    const data = async () => {
      await fetchMarketData();
    };
  }, [page]);

  const handleLoadMore = async () => {
    setFetching(true);
    setPage((page) => page + 1);
  };

  const ScreenA = () => (
    <FlatList
      data={data}
      style={{ backgroundColor: "white" }}
      keyExtractor={(item) => item.id}
      renderItem={renderItems}
      scrollEventThrottle={16}
      onEndReached={handleLoadMore}
      onEndReachedThreshold={0}
    />
  );  

  return (
    <Tab.Navigator
      screenOptions={({ route }) => screenOptions(route)}
      keyboardDismissMode="auto"
    >
      <Tab.Screen name="Crypto" component={ScreenA} />
      <Tab.Screen name="Forex" component={ScreenC} />
    </Tab.Navigator>
  );
};

export default Navigator;

OnEndReached 正在触发 handleLoadMore 函数,在数据状态更改后,Flatlist 滚动到顶部。

第一个原因

  • 你在“fetchMarketData”中有错字,你究竟是如何得到“newData”的,因为我在任何地方都看不到它,也许它应该是“marketData”,如果不是那么你添加相同的旧数据加上未定义的[...data, ...undefined]

第二个原因

你调用 setPage(page + 1) 然后调用“fetchMarketData”的原因,这很糟糕,为什么?因为 setState 是异步的,它可以立即或在 5 秒后改变,所以你不知道它什么时候改变的,这就是我们有钩子的原因,你可以使用“useEffect”来处理这个

像这样更改您的“handleLoadMore”

const handleLoadMore = () => {
    setPage(page + 1);
  };

添加在“页面”状态更改时运行的 useEffect 挂钩

React.useEffect(() => {
 (async() => {
    setFetching(true)
    const marketData = await getCryptoMarketData({ page });
    if (marketData != "Network Error") {
      setData([...data, ...marketData]);
    } else {
      Alert.alert(marketData, "Sorry for the inconvenience");
    }
    setFetching(false)
})()
}, [page])