react-native icon indicating copy to clipboard operation
react-native copied to clipboard

RefreshControl refresh indicator is not shown on iOS

Open danielmorlock opened this issue 2 years ago • 8 comments

Description

The refresh indicator for <RefreshControl /> is not shown in<ScrollView> and related components like <VirtualizedList /> and <FlatList /> etc.. when refreshing is initially set as true (i.e. refreshing={true}).

This happens in both, when using Expo Go and when using the build iOS app.

Version

0.69.7, 0.70.6

Output of npx react-native info

System: OS: Linux 5.15 Gentoo Linux CPU: (12) x64 Intel(R) Core(TM) i9-8950HK CPU @ 2.90GHz Memory: 16.15 GB / 62.44 GB Shell: 5.9 - /bin/zsh Binaries: Node: 16.17.0 - ~/.config/nvm/versions/node/v16.17.0/bin/node Yarn: 1.22.19 - ~/workspace/fgs/mobile/node_modules/.bin/yarn npm: 2.15.12 - ~/workspace/fgs/mobile/node_modules/.bin/npm Watchman: Not Found SDKs: Android SDK: Not Found IDEs: Android Studio: Not Found Languages: Java: 11.0.15 - /usr/bin/javac npmPackages: @react-native-community/cli: Not Found react: 18.0.0 => 18.0.0 react-native: 0.69.6 => 0.69.6 npmGlobalPackages: react-native: Not Found

Steps to reproduce

<ScrollView
        contentContainerStyle={styles.scrollView}
        refreshControl={
          <RefreshControl
            refreshing={true}
            onRefresh={onRefresh}
          />
        }
      >
        <Text>
        This refresh indicator is not shown on iOS
        </Text>
      </ScrollView>

Snack, code example, screenshot, or link to a repository

https://snack.expo.dev/@danielmorlock/refresh-indicator-bug

danielmorlock avatar Jan 05 '23 13:01 danielmorlock

I'm also having this issue. To resolve I'm setting refreshing boolean after 10 mills

const fetchData = ()=>{
    this.setRefreshing(true)
    //... data fetching logic
}


React.useEffect(() => {
    setTimeout(() => {
        state.fetchData()
    }, 10)
}, [])

ngima avatar Jan 23 '23 12:01 ngima

I am also having this issue, the RefreshControl will not show when initially set to true. It will only show on pull to refresh

built-by-as avatar Mar 28 '23 18:03 built-by-as

I am also having this issue, any update?

Alecattie avatar Apr 17 '23 06:04 Alecattie

I was able to work around with setTimeout as @ngima mentioned above:

import { useEffect, useState } from 'react';
import {
  RefreshControlProps,
  RefreshControl as RefreshControlRN,
} from 'react-native';

export function RefreshControl({ refreshing, ...other }: RefreshControlProps) {
  const [isRefreshing, setRefreshing] = useState(false);
  useEffect(() => {
    setTimeout(() => {
      setRefreshing(refreshing);
    }, 10);
  }, [refreshing]);
  return <RefreshControlRN refreshing={isRefreshing} {...other} />;
}

madox2 avatar Aug 17 '23 15:08 madox2

This issue is stale because it has been open 180 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Feb 14 '24 05:02 github-actions[bot]

It’s still a problem…

zackify avatar Feb 14 '24 13:02 zackify

I am experiencing this exact problem. In the code example (or in your app), if you pull the screen down a bit you can see the loading icon so it's there, just not visible.

saurori avatar Feb 21 '24 20:02 saurori

same

w3company-leo avatar Feb 23 '24 07:02 w3company-leo

I have implemented a workaround by programmatically scrolling the view slightly, which makes the hidden refresh control visible on iOS.

import React, { useRef, useState, useEffect } from 'react';
import { ScrollView, RefreshControl } from 'react-native';

const App = () => {
  ....
  const [loading, setLoading] = useState<boolean>(true);

  const scrollRef = useRef<ScrollView>(null);

  useEffect(() => {
    setTimeout(() => {
      scrollRef?.current?.scrollTo({ y: -50 });
    }, 500);
    fetchData();
  }, []);

  const fetchData = () => {
    setLoading(true)
    // Your refresh logic here
    setLoading(false)
  };

  ....
  
  return (
    <ScrollView
      ref={scrollRef}
      refreshControl={
        <RefreshControl
          refreshing={loading}
          onRefresh={fetchData}
        />
      }
    >
    ....
    ....
    </ScrollView>
  );
};

The above code uses a useRef to hold a reference to the <ScrollView>. In the useEffect, it programmatically scrolls the view slightly upwards after a delay, which makes the refresh control visible.

This workaround ensures that the refresh control is displayed properly on iOS when the refreshing prop is true without pulling.

Thanhal-P-A avatar May 17 '24 15:05 Thanhal-P-A

We are having the same issue with FlashList. It's also reported on that repo but the issue is not of the library but of react native. https://github.com/Shopify/flash-list/issues/875

lsarni avatar Jul 16 '24 13:07 lsarni