Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RefreshControl does not work correctly on state change #24855

Closed
gzzo opened this issue May 14, 2019 · 30 comments
Closed

RefreshControl does not work correctly on state change #24855

gzzo opened this issue May 14, 2019 · 30 comments

Comments

@gzzo
Copy link

gzzo commented May 14, 2019

React Native version:
0.59.8

Steps To Reproduce

  1. Pull down on list, refresh control appears (as it should)
  2. Press button on top of list to load data, refresh control does not appear even though refreshing is true. You can also this is true by pressing the button first, the pulling down, then finally pressing the button again.

Describe what you expected to happen: The refresh control should appear whenever refreshing is true

Snack, code example, or link to a repository: https://snack.expo.io/ByZXxOuhV

@stale
Copy link

stale bot commented Aug 12, 2019

Hey there, it looks like there has been no activity on this issue recently. Has the issue been fixed, or does it still require the community's attention? This issue may be closed if no further activity occurs. You may also label this issue as a "Discussion" or add it to the "Backlog" and I will leave it open. Thank you for your contributions.

@stale stale bot added the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 12, 2019
@gzzo
Copy link
Author

gzzo commented Aug 12, 2019

This is still an issue

@stale stale bot removed the Stale There has been a lack of activity on this issue and it may be closed soon. label Aug 12, 2019
@danieloprado
Copy link

Problem stills on 0.60.4

@gbalduzzi
Copy link

gbalduzzi commented Aug 20, 2019

Can confirm, it is really annoying because there are no actual workarounds if you need to:

  • Keep pull to refresh functionality
  • Show the loading indicator when the refresh is triggered programmatically (e.g. the user searched something)

I noticed it only happens on iOS (I tested on Android 9.0.0 and it works properly)

@xfyre
Copy link

xfyre commented Sep 3, 2019

+1

Android works properly, while iOS does not. Somehow refreshing state doesn't keep on the screen while app is reloading and resets immediately.

@ilkka-yli
Copy link

+1

I have this issue too. RN version 0.59.8.

@SergioCastro15
Copy link

+1
0.60.4, it happens only in iOS with the controlled prop

@patrickleemsantos
Copy link

patrickleemsantos commented Sep 10, 2019

+1 I also experience in RN 0.59.8 on IOS only

@zyc67
Copy link

zyc67 commented Sep 23, 2019

+1 ios
when I use react-navigation to customize the header, and set the navigation height by headerStyle, the problem appear, if I remove the header it's ok.

@plimerence
Copy link

same issue ,why so much bugs in basic component🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃🙃

@jmkitavi
Copy link

jmkitavi commented Oct 9, 2019

+1
RN 0.60.4, Same issue.
Doesn't work on iOS but works perfectly on Android.

@jmkitavi
Copy link

jmkitavi commented Oct 9, 2019

#24530

@gbalduzzi
Copy link

gbalduzzi commented Oct 10, 2019

I had to use a very hacky and very wrong workaround to make it work.

Basically, I noticed that it worked the first time (usually while loading the initial data at screen startup) but stopped working after that. So, I force the component (a FlatList in my case) to re-render completely after each successful refreshcontrol appearance, by changing its key attribute.

Honestly, it sucks, and it could not be feasible on lists with a lot of components to re render, but in my case it works well enough.

export default class extends React.Component {
  flastListKey = 0

  constructor(props) {
    super(props)
    this.state = {
      loading: false
    }
  }

  render () {
    <FlatList
      key={this.flatListKey}
      refreshing={this.state.loading}
      onRefresh={() => this.refreshData()}
      {... other props}
      />
  }

  refreshData = () => {
    this.setLoading(true)

    // DO stuff

    setTimeout(() => {
      this.setLoading(false)
    }, 2000)
  }

  setLoading = (loading: boolean) => {
    let shouldResetFlatlist = this.state.loading && !loading

    this.setState(
      {
        loading: loading,
      },
      () => {
        if (shouldResetFlatlist) {
          this.resetFlatlist()
        }
      },
    )
  }

  resetFlatlist = () => {
    if (Platform.OS === 'ios') {
      this.flatListKey = Math.random() * 1000
      setTimeout(() => {
        this.forceUpdate()
      }, 250)
    }
  }
}

The timeout is necessary to wait for the RefreshControl animation to finish

@jlariza
Copy link

jlariza commented Oct 25, 2019

+1
RN 0.61.2 failing as well. It doesn't work on iOS but works perfectly on Android.

@daysv
Copy link

daysv commented Oct 31, 2019

+1
RN 0.61.2, Same issue.
thanks @gbalduzzi

@swain
Copy link

swain commented Nov 12, 2019

+1
Still seeing this issue!

@ragamufin
Copy link

See my comment here for a possible workaround

@IgnorancePulls
Copy link

Opened Pr ^

@rdinizz
Copy link

rdinizz commented Mar 19, 2020

If anyone is still having problems with this:

I found a workaround that is just enabling the bounce.

I had bounces={false} and after removing it, it's working on iOS now(Android was already working)

But in my case, the loading didn't appear not even once.

@obiwankenoobi
Copy link

still an issue with v0.61.4

@emagnier
Copy link

emagnier commented Jun 3, 2020

still an issue on v0.62.2 when <RefreshControl /> is enabled (with local state) from a useEffect function.

@hackrx
Copy link

hackrx commented Jun 4, 2020

Hey, guys, I am facing the same issue with android, please have a look at this code, don't know why it is not working

  constructor(props) {
    super(props);
    this.state = {
      loading: false,
      lastLoadDate: null,
      onPullRefresh: false,
      postArray: [],
      allLoadDone: false,
      limit: 5,
      refreshing: false,
    };
    this.onEndReachedCalledDuringMomentum = false;
  }
componentDidMount() {
 console.log(
   'Component did mount Home.js retrieve data called',
   this.state.postArray,
 );
 this.retrieveData();
} 
 <View style={styles.listView}>
          <FlatList
            //data

            style={{width: '100%'}}
            data={this.state.postArray}
            extraData={this.state}
            //renderItems
            renderItem={({item}) => (
              <Post
                userName={item.userName}
                userPhoto={item.userPhotoURL}
                imageData={item.postImageURL}
                likes={item.likes}
                // id={item.}
                title={item.title}
                hashtags={item.hashtags}
                resizeMode={item.style}
                timeStamp={item.createdAt}
                navigation={this.props.navigation}
              />
            )}
            //Item Key
            keyExtractor={(item, index) => String(index)}
            //Footer loader
            ListFooterComponent={this.renderFooter}
            //on end reached

            onEndReached={() => {
              if (!this.onEndReachedCalledDuringMomentum) {
                // if (allLoadDone) {
                //   noRetrieve();
                // } else {
                this.retrieveMore();
                // }
              }
            }}
            onMomentumScrollBegin={() => {
              this.onEndReachedCalledDuringMomentum = false;
            }}
            refreshControl={
              <RefreshControl
                refreshing={this.state.onPullRefresh}
                colors={[PrimaryColor, SecondaryColor, 'white']}
                progressBackgroundColor="pink"
                onRefresh={this.retrieveData}
                enabled={true}
                
              />
            }
            // How Close To The End Of List Until Next Data Request Is Made
            onEndReachedThreshold={0.1}
            showsVerticalScrollIndicator={false} //hides the vertical scroll
            refreshing={this.state.refreshing}
          />

@fukemy
Copy link

fukemy commented Apr 15, 2022

same problem here, refreshControl does not show first time in useEffect even i set showState to true

refreshControl={
          <RefreshControl
            tintColor={theme.mainOrangeColor}
            refreshing={isRefreshing}
            onRefresh={() => {
              console.log('onrefresh')
              skip = 0
              _getRoomList()
            }}
          /> 
        }

facebook-github-bot pushed a commit that referenced this issue Sep 8, 2022
Summary:
This sync includes the following changes:
- **[4ea064eb0](facebook/react@4ea064eb0 )**: Don't fire passive effects during initial mount of a hidden Offscreen tree ([#24967](facebook/react#24967)) //<Andrew Clark>//
- **[2c7dea736](facebook/react@2c7dea736 )**: Implement Offscreen in Fizz ([#24988](facebook/react#24988)) //<Andrew Clark>//
- **[49f8254d6](facebook/react@49f8254d6 )**: Bug fix for <App /> vs. <Counter /> ([#24972](facebook/react#24972)) //<davidrenne>//
- **[6b28bc9c5](facebook/react@6b28bc9c5 )**: test: Throw custom error instead of relying on runtime error ([#24946](facebook/react#24946)) //<Sebastian Silbermann>//
- **[9bd0dd4c1](facebook/react@9bd0dd4c1 )**: test(react-debug-tools): Improve coverage of currentDispatcher.current setter ([#24945](facebook/react#24945)) //<Sebastian Silbermann>//
- **[59bc52a16](facebook/react@59bc52a16 )**: Add 4.5.0 release to eslint rules CHANGELOG ([#24853](facebook/react#24853)) //<Sebastian Silbermann>//
- **[cfb6cfa25](facebook/react@cfb6cfa25 )**: Reused components commit with timing as new ones //<Andrew Clark>//
- **[679eea328](facebook/react@679eea328 )**: Extract layout effects to separate functions //<Andrew Clark>//
- **[41287d447](facebook/react@41287d447 )**: Use recursion to traverse during "reappear layout" phase //<Andrew Clark>//
- **[697702bf3](facebook/react@697702bf3 )**: Use recursion to traverse during "disappear layout" phase //<Andrew Clark>//
- **[02206099a](facebook/react@02206099a )**: Use recursion to traverse during passive unmount phase ([#24918](facebook/react#24918)) //<Andrew Clark>//
- **[f62949519](facebook/react@f62949519 )**: [Transition Tracing] Rename transitionCallbacks to unstable_transitionCallbacks  ([#24920](facebook/react#24920)) //<Luna Ruan>//
- **[7a4336c40](facebook/react@7a4336c40 )**: Use recursion to traverse during passive mount phase //<Andrew Clark>//
- **[bb1357b38](facebook/react@bb1357b38 )**: Wrap try-catch directly around each user function //<Andrew Clark>//
- **[de3c06984](facebook/react@de3c06984 )**: Move flag check into each switch case //<Andrew Clark>//
- **[f5916d15b](facebook/react@f5916d15b )**: [Transition Tracing][Code Cleanup] Delete Marker Name Change Tests ([#24908](facebook/react#24908)) //<Luna Ruan>//
- **[fa20b319f](facebook/react@fa20b319f )**: [Transition Tracing] Code Cleanup ([#24880](facebook/react#24880)) //<Luna Ruan>//
- **[5e8c1961c](facebook/react@5e8c1961c )**: [Transition Tracing] onMarkerProgress ([#24861](facebook/react#24861)) //<Luna Ruan>//
- **[b641d0209](facebook/react@b641d0209 )**: Use recursion to traverse during layout phase //<Andrew Clark>//
- **[a1b1e391e](facebook/react@a1b1e391e )**: Wrap try-catch directly around each user function //<Andrew Clark>//
- **[3df7e8f5d](facebook/react@3df7e8f5d )**: Move flag check into each switch case //<Andrew Clark>//
- **[b8c96b136](facebook/react@b8c96b136 )**: Move ref commit effects inside switch statement //<Andrew Clark>//
- **[e225fa43a](facebook/react@e225fa43a )**: [Transition Tracing] Don't call transition callbacks if no transition name specified ([#24887](facebook/react#24887)) //<Luna Ruan>//
- **[dd2d65227](facebook/react@dd2d65227 )**: [Transition Tracing] Tracing Marker Name Change in Update Warning ([#24873](facebook/react#24873)) //<Luna Ruan>//
- **[80208e769](facebook/react@80208e769 )**: [Transition Tracing] Add onTransitionProgress Callback ([#24833](facebook/react#24833)) //<Luna Ruan>//
- **[30eb267ab](facebook/react@30eb267ab )**: Land forked reconciler changes ([#24878](facebook/react#24878)) //<Andrew Clark>//
- **[5e4e2dae0](facebook/react@5e4e2dae0 )**: Defer setState callbacks until component is visible ([#24872](facebook/react#24872)) //<Andrew Clark>//
- **[8e35b5060](facebook/react@8e35b5060 )**: [Transition Tracing] Refactor Code to Remove OffscreeInstance TODOs ([#24855](facebook/react#24855)) //<Luna Ruan>//
- **[deab1263a](facebook/react@deab1263a )**: [Transition Tracing] Change Transition Type Passed Pending Transitions ([#24856](facebook/react#24856)) //<Luna Ruan>//
- **[82e9e9909](facebook/react@82e9e9909 )**: Suspending inside a hidden tree should not cause fallbacks to appear ([#24699](facebook/react#24699)) //<Andrew Clark>//

Changelog:
[General][Changed] - React Native sync for revisions c1f5884...4ea064e

jest_e2e[run_all_tests]

Reviewed By: philIip, NickGerleman

Differential Revision: D39305648

fbshipit-source-id: 627ead5035c77fbc902b306e17897e425ad7fb99
OlimpiaZurek pushed a commit to OlimpiaZurek/react-native that referenced this issue May 22, 2023
Summary:
This sync includes the following changes:
- **[4ea064eb0](facebook/react@4ea064eb0 )**: Don't fire passive effects during initial mount of a hidden Offscreen tree ([facebook#24967](facebook/react#24967)) //<Andrew Clark>//
- **[2c7dea736](facebook/react@2c7dea736 )**: Implement Offscreen in Fizz ([facebook#24988](facebook/react#24988)) //<Andrew Clark>//
- **[49f8254d6](facebook/react@49f8254d6 )**: Bug fix for <App /> vs. <Counter /> ([facebook#24972](facebook/react#24972)) //<davidrenne>//
- **[6b28bc9c5](facebook/react@6b28bc9c5 )**: test: Throw custom error instead of relying on runtime error ([facebook#24946](facebook/react#24946)) //<Sebastian Silbermann>//
- **[9bd0dd4c1](facebook/react@9bd0dd4c1 )**: test(react-debug-tools): Improve coverage of currentDispatcher.current setter ([facebook#24945](facebook/react#24945)) //<Sebastian Silbermann>//
- **[59bc52a16](facebook/react@59bc52a16 )**: Add 4.5.0 release to eslint rules CHANGELOG ([facebook#24853](facebook/react#24853)) //<Sebastian Silbermann>//
- **[cfb6cfa25](facebook/react@cfb6cfa25 )**: Reused components commit with timing as new ones //<Andrew Clark>//
- **[679eea328](facebook/react@679eea328 )**: Extract layout effects to separate functions //<Andrew Clark>//
- **[41287d447](facebook/react@41287d447 )**: Use recursion to traverse during "reappear layout" phase //<Andrew Clark>//
- **[697702bf3](facebook/react@697702bf3 )**: Use recursion to traverse during "disappear layout" phase //<Andrew Clark>//
- **[02206099a](facebook/react@02206099a )**: Use recursion to traverse during passive unmount phase ([facebook#24918](facebook/react#24918)) //<Andrew Clark>//
- **[f62949519](facebook/react@f62949519 )**: [Transition Tracing] Rename transitionCallbacks to unstable_transitionCallbacks  ([facebook#24920](facebook/react#24920)) //<Luna Ruan>//
- **[7a4336c40](facebook/react@7a4336c40 )**: Use recursion to traverse during passive mount phase //<Andrew Clark>//
- **[bb1357b38](facebook/react@bb1357b38 )**: Wrap try-catch directly around each user function //<Andrew Clark>//
- **[de3c06984](facebook/react@de3c06984 )**: Move flag check into each switch case //<Andrew Clark>//
- **[f5916d15b](facebook/react@f5916d15b )**: [Transition Tracing][Code Cleanup] Delete Marker Name Change Tests ([facebook#24908](facebook/react#24908)) //<Luna Ruan>//
- **[fa20b319f](facebook/react@fa20b319f )**: [Transition Tracing] Code Cleanup ([facebook#24880](facebook/react#24880)) //<Luna Ruan>//
- **[5e8c1961c](facebook/react@5e8c1961c )**: [Transition Tracing] onMarkerProgress ([facebook#24861](facebook/react#24861)) //<Luna Ruan>//
- **[b641d0209](facebook/react@b641d0209 )**: Use recursion to traverse during layout phase //<Andrew Clark>//
- **[a1b1e391e](facebook/react@a1b1e391e )**: Wrap try-catch directly around each user function //<Andrew Clark>//
- **[3df7e8f5d](facebook/react@3df7e8f5d )**: Move flag check into each switch case //<Andrew Clark>//
- **[b8c96b136](facebook/react@b8c96b136 )**: Move ref commit effects inside switch statement //<Andrew Clark>//
- **[e225fa43a](facebook/react@e225fa43a )**: [Transition Tracing] Don't call transition callbacks if no transition name specified ([facebook#24887](facebook/react#24887)) //<Luna Ruan>//
- **[dd2d65227](facebook/react@dd2d65227 )**: [Transition Tracing] Tracing Marker Name Change in Update Warning ([facebook#24873](facebook/react#24873)) //<Luna Ruan>//
- **[80208e769](facebook/react@80208e769 )**: [Transition Tracing] Add onTransitionProgress Callback ([facebook#24833](facebook/react#24833)) //<Luna Ruan>//
- **[30eb267ab](facebook/react@30eb267ab )**: Land forked reconciler changes ([facebook#24878](facebook/react#24878)) //<Andrew Clark>//
- **[5e4e2dae0](facebook/react@5e4e2dae0 )**: Defer setState callbacks until component is visible ([facebook#24872](facebook/react#24872)) //<Andrew Clark>//
- **[8e35b5060](facebook/react@8e35b5060 )**: [Transition Tracing] Refactor Code to Remove OffscreeInstance TODOs ([facebook#24855](facebook/react#24855)) //<Luna Ruan>//
- **[deab1263a](facebook/react@deab1263a )**: [Transition Tracing] Change Transition Type Passed Pending Transitions ([facebook#24856](facebook/react#24856)) //<Luna Ruan>//
- **[82e9e9909](facebook/react@82e9e9909 )**: Suspending inside a hidden tree should not cause fallbacks to appear ([facebook#24699](facebook/react#24699)) //<Andrew Clark>//

Changelog:
[General][Changed] - React Native sync for revisions c1f5884...4ea064e

jest_e2e[run_all_tests]

Reviewed By: philIip, NickGerleman

Differential Revision: D39305648

fbshipit-source-id: 627ead5035c77fbc902b306e17897e425ad7fb99
@madebyrogal
Copy link

The issue is still there in iOS.
RN ver: 0.71.8

@Danushka50
Copy link

Danushka50 commented Aug 7, 2023

Added a solution but not the perfect one.

#37308 (comment)

@fukemy
Copy link

fukemy commented Aug 8, 2023

I am trying to implement release to refresh, not pull to refresh but not working

@fswienty
Copy link

fswienty commented Apr 26, 2024

The issue still persists for me on Android with RN 0.72.6. When I set data={[]} in my flatlist, the refresh control works as it should, but when attempting to show data fetched via tanstack query, the refresh control will not show anymore after the list is populated.*

EDIT: It turned out I screwed up my imports and accidentally used the FlatList from react-native-gesture-handler instead of the one from react-native. The FlatList from react-native works perfectly fine. So if you have this issue, check your imports, maybe the solution is as simple as that.

I'm going to look for a dunce cap now.

@dcdavidheisnam
Copy link

It's still happening on iOS

@thianphat
Copy link

Happening to me as well

@alimohsinz
Copy link

alimohsinz commented Oct 31, 2024

i have fixed it using below workaround but i dont even know why its working.
Please also explain me if you got it.

Add ListEmptyComponent and pass loading prop to it

 <FlatList
        style={{flex: 1}}
        data={artistList}
        renderItem={({item}) => <ArtistCard item={item} />}
        refreshing={loading}
        refreshControl={
          <RefreshControl
            colors={['black']}
            tintColor="white"
            refreshing={loading}
            onRefresh={getArtistsList}
          />
        }
        ListEmptyComponent={<ListEmptyCompnent loader={loading} />}
        keyExtractor={item => `${item._id}`}
        contentContainerStyle={{
          paddingTop: 20,
        }}
      />

in ListEmptyCompnent if loading is true show a string with spaces inside

    const ListEmptyCompnent = ({loader}: {loader: boolean}) => {
 const {colors, fontFamily, fontSize} = useTheme() as any;

 return (
   <View style={{justifyContent: 'center', alignItems: 'center'}}>
     {loader ? (
       // to fix loader not showing on first render
       <Text
         style={{
           color: colors.bodyText,
           fontSize: fontSize.bodyTextFont,
           fontFamily: fontFamily.mainheading,
         }}>
         {'           '}
       </Text>
     ) : (
       <Text
         style={{
           color: colors.bodyText,
           fontSize: fontSize.bodyTextFont,
           fontFamily: fontFamily.mainheading,
         }}>
         No Item to Display
       </Text>
     )}
   </View>
 );
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment