RefreshControl - Pull to Refresh in React Native Apps
Tags: reactnative, refresh, reload, functionality
Published: 2020-03-29 22:29:35

<main role="main"><article class=" u-minHeight100vhOffset65 u-overflowHidden postArticle postArticle--full is-supplementalPostContentLoaded is-withAccentColors" lang="en"><div class="postArticle-content js-postField js-notesSource editable" id="editor_6" g_editable="true" role="textbox" contenteditable="true" data-default-value="Title
Tell your story…" spellcheck="false"><section name="f546" class="section section--body section--first section--last"><div class="section-divider"><hr class="section-divider"></div><div class="section-content"><div class="section-inner sectionLayout--insetColumn"><p name="64d4" class="graf graf--p graf-after--figure">In this post, you will learn how to implement <strong class="markup--strong markup--p-strong">Pull to Refresh functionality</strong> in React Native apps. We will implement this in a simple React Native app and test on device.</p><p name="e799" class="graf graf--p graf-after--p">Pull-to-refresh is the functionality we use to refresh data in our apps, where we pull the screen towards bottom to load new data. See example below</p><figure tabindex="0" contenteditable="false" name="cc78" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 540px; max-height: 317px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 58.699999999999996%;"></div><img class="graf-image" data-image-id="0*pxkp28b2VlZg8wt8.gif" data-width="540" data-height="317" src="https://cdn-images-1.medium.com/max/800/0*pxkp28b2VlZg8wt8.gif"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Pull to Refresh Example in&nbsp;Android</figcaption></figure><p name="6b38" class="graf graf--p graf-after--figure">Few great examples are Instagram or Facebook. Pull to refresh is important in any app where you have a data feed, which needs to be refreshed. This happens mostly when your users spend a good amount of time on the app, and during that time, more data is generate to show them.</p><blockquote name="da96" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong">Complete source code of this tutorial is available in the </strong><a href="https://github.com/enappd/react-native-pull-to-refresh"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">react-native-pull-to-refresh</strong></a><strong class="markup--strong markup--blockquote-strong"> repository</strong></blockquote><h3 name="b6ca" class="graf graf--h3 graf-after--blockquote">What is React-Native</h3><p name="0fc5" class="graf graf--p graf-after--h3">Before we move into the blog, let’s first clarify what framework we are using. We are using React Native, which is one among many hybrid app frameworks available. The closest rivals of React Native are Flutter and Ionic.</p><p name="e27d" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">TLDR;</strong>&#8202;—&#8202;React Native (RN) apps are more “native” than web-view apps made by Cordova / Ionic. React Native crates actual Java and Swift codes for apps, unlike the web-view apps which essentially run in a&nbsp;… web-view.</p><p name="d619" class="graf graf--p graf-after--p">React Native is a JavaScript framework for writing natively rendering mobile applications. It’ is based on React, Facebook’s JavaScript library for building user interfaces, but instead of targeting the browser, it targets mobile platforms. Because most of the code you write can be shared between platforms, React Native makes it easy to simultaneously develop for both Android and iOS.</p><p name="de54" class="graf graf--p graf-after--p">React Native applications render using real mobile UI components, <em class="markup--em markup--p-em">not</em> web-views, and will look and feel like any other native mobile application. React Native also exposes JavaScript interfaces for platform APIs, so your React Native apps can access platform features like the phone camera, or the user’s location. <a href="http://bit.ly/1YipO7A"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Facebook</a>, <a href="http://bit.ly/1PPEiZH"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Palantir</a>, <a href="http://bit.ly/1PPEjNg"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener"    target="_blank">TaskRabbit</a> etc are already using it in production for user-facing applications.</p><h3 name="a3b0" class="graf graf--h3 graf-after--p">Post structure</h3><p name="3480" class="graf graf--p graf-after--h3">We will go in a step-by-step manner to explore the pull to refresh feature of Firebase. This is my break-down of the blog</p><p name="1a45" class="graf graf--p graf-after--p"><strong class="markup--strong markup--p-strong">STEPS</strong></p><ol class="postList"><li name="c394" class="graf graf--li graf-after--p">Create a simple React Native app</li><li name="e24a" class="graf graf--li graf-after--li">Implement Pull to refresh functionality using mock APIs</li><li name="3666" class="graf graf--li graf-after--li">Build the app on Android device and test</li></ol><p name="08cb" class="graf graf--p graf-after--li">So let’s dive right in!</p><figure tabindex="0" contenteditable="false" name="8ea5" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 350px; max-height: 640px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 182.9%;"></div><img class="graf-image" data-image-id="1*ERffcqfeSC19qC5l50L94w.gif" data-width="350" data-height="640" src="https://cdn-images-1.medium.com/max/800/1*ERffcqfeSC19qC5l50L94w.gif"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">I made you laugh&nbsp;… didn’t I&nbsp;?&nbsp;😆</figcaption></figure><h3 name="5996" class="graf graf--h3 graf-after--figure">Step 1 - Create a basic React Native&nbsp;app</h3><p name="9b4d" class="graf graf--p graf-after--h3">First, make sure you have all pre-requisites to create a react-native app as per the <a href="https://facebook.github.io/react-native/docs/getting-started.html"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener"    target="_blank">official documentation</a>.</p><blockquote name="5518" class="graf graf--blockquote graf-after--p"><strong class="markup--strong markup--blockquote-strong"><em class="markup--em markup--blockquote-em">At the time of this post, I have React-Native version 0.61.5 &amp; node 10.16.0</em></strong></blockquote><p name="f921" class="graf graf--p graf-after--blockquote">Create a blank react-native app</p><pre name="b6c0" class="graf graf--pre graf-after--p">$ react-native init RNRefreshControl</pre><p name="4f66" class="graf graf--p graf-after--pre">This will create a basic React-native app which you can run in a device or simulator. (either Android or iOS)</p><p name="7bb3" class="graf graf--p graf-after--p">We’ll create a simple page with a list of items. This list will contain 5 items initially, but when we “pull to refresh”, another 5 items will add up in the list. The function will return a message when there is no new data available anymore. Initial page will look like this</p><figure tabindex="0" contenteditable="false" name="2578" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 323px; max-height: 700px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 216.7%;"></div><img class="graf-image" data-image-id="1*AMWE2q2bNljIjfqt82IKjQ.jpeg" data-width="323" data-height="700" alt="Initial Flatlist in React Native Pull to Refresh example" src="https://cdn-images-1.medium.com/max/800/1*AMWE2q2bNljIjfqt82IKjQ.jpeg"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Initial FlatList in React Native Pull to Refresh&nbsp;example</figcaption></figure><h3 name="b55b" class="graf graf--h3 graf-after--figure">Step 2&#8202;—&#8202;Implement Pull to refresh functionality using mock&nbsp;APIs</h3><h4 name="cff2" class="graf graf--h4 graf-after--h3">Create Mock API for&nbsp;data</h4><p name="e991" class="graf graf--p graf-after--h4">As explained above, our initial list will have 5 items. Once we pull to refresh, an API call is made. This will fetch 5 more list items. Let’s first create this API in <a href="http://mocky.io"  class="markup--anchor markup--p-anchor" rel="noopener"    target="_blank">mocky.io</a>. It’s a great way to mock your API calls.</p><figure tabindex="0" contenteditable="false" name="42a7" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 353px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 50.4%;"></div><img class="graf-image" data-image-id="1*TFRx7El0osxIZ6Y0v96iMA.png" data-width="994" data-height="501" alt="Mock your API call data by creating a mock API in mocky" src="https://cdn-images-1.medium.com/max/800/1*TFRx7El0osxIZ6Y0v96iMA.png"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Mock your API call data by creating a mock API in&nbsp;mocky</figcaption></figure><p name="1592" class="graf graf--p graf-after--figure">Our initial data is</p><pre name="c18e" class="graf graf--pre graf-after--p">const initialData = [<br>{<br> id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",<br> title: "Susan Bert",<br> image: "1"<br>},<br>{<br> id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",<br> title: "Neil Arms",<br> image: "2"<br>},<br>{<br> id: "58694a0f-3da1-471f-bd96-145571e29d72",<br> title: "Carla Neice",<br> image: "3"<br>},<br>{<br> id: "bd7acbea-c1b1-46c2-aed5-3ad53cbb28ba",<br> title: "Janice Hanner",<br> image: "4"<br>},<br>{<br> id: "3ac68afc-c605-48d3-a4f8-fcd91aa97f63",<br> title: "James Sullivan",<br> image: "5"<br>}];</pre><p name="9747" class="graf graf--p graf-after--pre">and similar 5 items will be fetched from API, which will add up in the list of items.</p><h4 name="f8ec" class="graf graf--h4 graf-after--p">Setup Pull to&nbsp;Refresh</h4><p name="968e" class="graf graf--p graf-after--h4">Pull to Refresh functionality is implemented using <code class="markup--code markup--p-code">RefreshControl</code> component in React Native. <code class="markup--code markup--p-code">RefreshControl</code> is used inside a ScrollView or ListView to add pull to refresh functionality. When the ScrollView is at <code class="markup--code markup--p-code">scrollY: 0</code>, swiping down triggers an <code class="markup--code markup--p-code">onRefresh</code> event.</p><p name="1180" class="graf graf--p graf-after--p">In our example, we are using a FlatList component to display the list. The FlatList code with <code class="markup--code markup--p-code">RefreshControl</code> looks like this</p><pre name="8f44" class="graf graf--pre graf-after--p">&lt;FlatList<br>data={listData}<br>renderItem={({ item }) =&gt; &lt;Item title={item.title} image={item.image} /&gt;}<br>keyExtractor={item =&gt; item.id}<br><strong class="markup--strong markup--pre-strong">refreshControl={&lt;RefreshControl refreshing={refreshing} onRefresh={onRefresh} /&gt;}</strong><br>contentContainerStyle={styles.list} /&gt;</pre><p name="bd45" class="graf graf--p graf-after--pre"><code class="markup--code markup--p-code">refreshing</code> is a controlled prop, this is why it needs to be set to <code class="markup--code markup--p-code">true</code> in the <code class="markup--code markup--p-code">onRefresh</code> function otherwise the refresh indicator will stop immediately.</p><p name="8707" class="graf graf--p graf-after--p">You can implement <code class="markup--code markup--p-code">RefreshControl</code> in ScrollView in a similar way.</p><p name="d671" class="graf graf--p graf-after--p">We will call the mock API in the <code class="markup--code markup--p-code">onRefresh</code> function, and append the result in <code class="markup--code markup--p-code">listData</code>&nbsp;. Here’s what the complete code looks like.</p><figure tabindex="0" contenteditable="false" name="5be1" class="graf graf--figure graf--iframe graf-after--p"><div class="aspectRatioPlaceholder is-locked"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 35.699999999999996%;"></div><div class="iframeContainer">{% gist https://gist.github.com/enappd/09aec44d4c7c119845492053608115b2.js %}</div></div><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for embed (optional)">Complete code to implement Pull to Refresh in React Native</figcaption></figure><p name="718a" class="graf graf--p graf-after--figure">Notice we have used React hooks to update data</p><pre name="0c85" class="graf graf--pre graf-after--p">const [listData, setListData] = React.useState(initialData);</pre><h3 name="a05e" class="graf graf--h3 graf-after--pre">Step 3: Testing the app on a&nbsp;device</h3><p name="838b" class="graf graf--p graf-after--h3">To run the iOS app, you should specify simulator</p><pre name="b815" class="graf graf--pre graf-after--p">$ react-native run-ios --simulator=”iPhone X”</pre><p name="9a4b" class="graf graf--p graf-after--pre">To run Android app, you should start emulator first (or connect a device), either via Android Studio or <code class="markup--code markup--p-code">adb</code>&nbsp;, then call</p><pre name="9e48" class="graf graf--pre graf-after--p">$ react-native run-android</pre><p name="eba0" class="graf graf--p graf-after--pre">Overall, the process will look something like this</p><figure tabindex="0" contenteditable="false" name="b233" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 393px; max-height: 700px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 178.1%;"></div><img class="graf-image" data-image-id="1*z4V1KxGjl4xzE2It6laotg.gif" data-width="393" data-height="700" src="https://cdn-images-1.medium.com/max/800/1*z4V1KxGjl4xzE2It6laotg.gif"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Pull to Refresh functionality in React Native&nbsp;app</figcaption></figure><p name="dfa5" class="graf graf--p graf-after--figure">You can see the first pull fetches 5 more data. After that our hacky logic tells the app there is no more data available. In real life scenario, your back-end will tell the app (via API) that no more data is available.</p><p name="4c18" class="graf graf--p graf-after--p">Tada&nbsp;! You have learnt how to implement Pull to Refresh in React Native app. 🎉</p><blockquote name="2ab1" class="graf graf--blockquote graf-after--p">Complete source code of this tutorial is available in the <a href="https://github.com/enappd/react-native-anonymous-login"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank">react-native-anonymous-login</a></blockquote><h3 name="7a48" class="graf graf--h3 graf-after--blockquote">Conclusion</h3><p name="7b07" class="graf graf--p graf-after--h3">In this blog, we learned how to implement Pull to Refresh functionality in React Native app. Pull to Refresh functionality is a must for an app where data changes very quickly, and where user spend good amount of time checking the feed. Pull to Refresh can be used in a FlatList or simple ScrollView as well. You can call custom functions during “refresh” event, and even display custom animations. Let me close the blog with some cool Pull-to-refresh animation.</p><figure tabindex="0" contenteditable="false" name="d2d4" class="graf graf--figure graf-after--p"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 525px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 75%;"></div><img class="graf-image" data-image-id="0*QYXR9yBhFQNBoF1-.gif" data-width="800" data-height="600" src="https://cdn-images-1.medium.com/max/800/0*QYXR9yBhFQNBoF1-.gif"><div class="crosshair u-ignoreBlock"></div></div><br/><figcaption class="imageCaption" contenteditable="true" data-default-value="Type caption for image (optional)">Try to make this as a refresh loader in your RN app&nbsp;!</figcaption></figure><blockquote name="d788" class="graf graf--blockquote graf-after--figure"><strong class="markup--strong markup--blockquote-strong">Complete source code of this tutorial is available in the </strong><a href="https://github.com/enappd/react-native-pull-to-refresh"  class="markup--anchor markup--blockquote-anchor" rel="noopener"    target="_blank"><strong class="markup--strong markup--blockquote-strong">react-native-pull-to-refresh</strong></a><strong class="markup--strong markup--blockquote-strong"> repository</strong></blockquote><h3 name="84b4" class="graf graf--h3 graf-after--blockquote">Next Steps</h3><p name="aae2" class="graf graf--p graf-after--h3 is-selected">Now that you have learnt about setting up Pull-to-Refresh in React Native apps, here are some other topics you can look into</p><ul class="postList"><li name="39b9" class="graf graf--li graf-after--p">Firebase&#8202;—&#8202;<a href="https://enappd.com/blog/intergrate-firebase-in-react-native-app/73"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Integrate Firebase</a> | <a href="https://enappd.com/blog/firebase-analytics-in-react-native-app/101"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Analytics</a> | <a href="https://enappd.com/blog/react-native-firebase-crud-image-upload-and-phone-authentication/86"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Push notifications</a> | <a href="https://enappd.com/blog/react-native-firebase-crud-image-upload-and-phone-authentication/86"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">Firebase CRUD</a></li><li name="ce44" class="graf graf--li graf-after--li">How To in React Native&#8202;—&#8202;<a href="https://enappd.com/blog/geolocation-geocoding-react-native-apps/84"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Geolocation</a> | <a href="https://enappd.com/blog/react-native-life-cycle-hooks/79"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Life cycle hooks</a> | <a href="https://enappd.com/blog/pick-images-from-camera-gallery-in-react-native-app/78"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Image Picker</a> | <a href="https://enappd.com/blog/redux-in-react-native-app/92"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Redux implementation</a> | <a href="https://enappd.com/blog/how-to-make-api-calls-in-react-native-apps/125"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Make API calls</a> | <a href="https://enappd.com/blog/navigations-in-react-native-app/124"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Navigation</a> | <a href="https://enappd.com/blog/how-to-translate-in-react-native-app-globalization-internationalization-and-text-to-speech/120"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Translation</a> | <a href="https://enappd.com/blog/react-native-qr-code-scanning-using-react-native-camera/117"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Barcode &amp; QR code scan</a> | <a href="https://enappd.com/blog/send-read-and-delete-sms-in-react-native/107"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Send &amp; Read SMS</a> | <a href="https://enappd.com/blog/google-vision-with-react-native/96"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Google Vision</a></li><li name="e480" class="graf graf--li graf-after--li">Payments&#8202;—&#8202;<a href="https://enappd.com/blog/implement-apple-pay-in-react-native-apps/93"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Apple Pay</a> | <a href="https://enappd.com/blog/stripe-integration-in-react-native-apps-using-firebase/108"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Stripe payments</a></li><li name="4d3b" class="graf graf--li graf-after--li">Authentication&#8202;—&#8202;<a href="https://enappd.com/blog/google-login-in-react-native-android-apps-with-firebase/90"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Google Login</a>| <a href="https://enappd.com/blog/facebook-login-in-react-native-apps/89"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Facebook login</a> | <a href="https://enappd.com/blog/react-native-firebase-crud-image-upload-and-phone-authentication/86"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Phone Auth</a> | <a href="https://enappd.com/blog/twitter-login-in-react-native-apps-using-firebase/95"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Twitter login</a></li><li name="2ccd" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/how-to-make-stories-ui-like-instagram-and-whatsapp-in-react-native/123"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Create Instagram / Whatsapp Story Feature in React Native</a></li><li name="01c3" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/react-native-life-cycle-hooks/79"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener noopener"    target="_blank">React Native life cycle hooks</a> | <a href="https://enappd.com/blog/redux-in-react-native-app/92"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Implement Redux</a> | <a href="https://enappd.com/blog/async-actions-with-redux-thunk-middleware-in-react-native-apps-1/100"  class="markup--anchor markup--li-anchor" rel="noopener"    target="_blank">Async actions with Redux</a></li><li name="3172" class="graf graf--li graf-after--li"><a href="https://enappd.com/blog/guide-on-react-native-full-app/53"  class="markup--anchor markup--li-anchor" rel="noopener nofollow noopener noopener"    target="_blank">Create Awesome Apps in React Native</a> using Full App</li></ul><p name="5017" class="graf graf--p graf-after--li">If you need a base to start your next React Native app, you can make your next awesome app using <a href="https://store.enappd.com/product/react-native-full-app/"  class="markup--anchor markup--p-anchor" rel="noopener nofollow noopener noopener"    target="_blank">React Native Full App</a></p><figure tabindex="0" contenteditable="false" name="a0ad" class="graf graf--figure graf-after--p is-defaultValue"><div class="aspectRatioPlaceholder is-locked" style="max-width: 700px; max-height: 700px;"><div class="aspectRatioPlaceholder-fill" style="padding-bottom: 100%;"></div><img class="graf-image" data-image-id="0*50h94UU2H2pkisje.jpeg" data-width="800" data-height="800" src="https://cdn-images-1.medium.com/max/800/0*50h94UU2H2pkisje.jpeg"><div class="crosshair u-ignoreBlock"></div></div></figure><p name="a3a4" class="graf graf--p graf--empty graf-after--figure graf--trailing"><br></p></div></div></section></div></article></main>