{"id":613,"date":"2019-02-17T23:54:21","date_gmt":"2019-02-17T23:54:21","guid":{"rendered":"http:\/\/upmostlymulti.onpressidium.com\/?p=613"},"modified":"2022-10-28T11:05:48","modified_gmt":"2022-10-28T16:05:48","slug":"build-an-infinite-scroll-component-in-react-using-react-hooks","status":"publish","type":"post","link":"http:\/\/upmostly.com\/tutorials\/build-an-infinite-scroll-component-in-react-using-react-hooks","title":{"rendered":"Build an Infinite Scroll Component in React using React Hooks"},"content":{"rendered":"\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"530\" src=\"http:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-react-hooks-1024x530.jpg\" alt=\"\" class=\"wp-image-679\" srcset=\"https:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-react-hooks-1024x530.jpg 1024w, https:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-react-hooks-300x155.jpg 300w, https:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-react-hooks-768x397.jpg 768w, https:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-react-hooks.jpg 1160w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>Today we&#8217;re going to dive deeper into React development and learn how to build an infinite scroll component in React using React Hooks. If you are just starting out with React hooks make sure to check out <a href=\"http:\/\/upmostly.com\/tutorials\/react-hooks-simple-introduction\" target=\"_blank\" data-type=\"URL\" data-id=\"http:\/\/upmostly.com\/tutorials\/react-hooks-simple-introduction\" rel=\"noreferrer noopener\">this guide<\/a>. If not, Let&#8217;s get started!<\/p>\n\n\n\n<div class=\"wp-block-columns has-2-columns is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex\">\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-button aligncenter is-style-outline is-style-outline--1\"><a class=\"wp-block-button__link has-vivid-cyan-blue-color has-text-color\" href=\"https:\/\/enigmatic-sierra-99668.herokuapp.com\/\" target=\"_blank\" rel=\"noopener\">View Demo<\/a><\/div>\n<\/div>\n\n\n\n<div class=\"wp-block-column is-layout-flow wp-block-column-is-layout-flow\">\n<div class=\"wp-block-button aligncenter is-style-outline is-style-outline--2\"><a class=\"wp-block-button__link has-very-dark-gray-color has-text-color\" href=\"https:\/\/github.com\/Upmostly\/react-hooks-infinite-scroll\" target=\"_blank\" rel=\"noopener\">View Code<\/a><\/div>\n<\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">What We&#8217;re Building<\/h2>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"570\" height=\"680\" src=\"http:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-demo.gif\" alt=\"A webpage showing a list of items that when scrolled to the bottom of the page, the list loads more items infinitely.\" class=\"wp-image-616\"\/><figcaption>What we&#8217;re building &#8212; an infinite scroll component that uses React Hooks!<\/figcaption><\/figure>\n\n\n\n<p>You may not have heard of an infinite scroller before, but if you&#8217;ve ever used Facebook, Instagram or Reddit,  you&#8217;ve definitely used one.<\/p>\n\n\n\n<p>An infinite scroller is a modern  alternative to  pagination. <\/p>\n\n\n\n<p>Rather than wait for the user to click <em>next page<\/em>, new content is automatically loaded every time the user reaches the bottom of the page. Therefore, there&#8217;s a never-ending supply of content for the user to read through.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Setting Up our Infinite Scroll Component<\/h2>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>If you have an existing React project that you want to add the infinite scroller functionality to, you can skip this section.<\/p><\/blockquote>\n\n\n\n<p>For everyone else, the easiest way to get started is to use&nbsp;<a aria-label=\"For everyone else, the easiest way to get started is to use&nbsp;Create React App&nbsp;to create a brand new React project. Follow the instructions over on their GitHub page. (opens in a new tab)\" href=\"https:\/\/github.com\/facebook\/create-react-app\" target=\"_blank\" rel=\"noreferrer noopener\">Create React App<\/a>&nbsp;to create a brand new React project. Check out this <a href=\"http:\/\/upmostly.com\/tutorials\/react-hello-world-your-first-react-app\" target=\"_blank\" data-type=\"URL\" data-id=\"http:\/\/upmostly.com\/tutorials\/react-hello-world-your-first-react-app\" rel=\"noreferrer noopener\">guide to creating your first React app<\/a>.<\/p>\n\n\n\n<p>Once you have the app up and running, strip out all of the unneccesary code from the&nbsp;<strong><span class=\"has-inline-color has-vivid-red-color\">App.js<\/span><\/strong>&nbsp;component, so it looks like this:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>I&#8217;m using Bootstrap in this tutorial. If you want to add bootstrap to your new React project, run the following command in your terminal at your  root project directory: <g class=\"gr_ gr_4 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling\" id=\"4\" data-gr-id=\"4\">npm<\/g> install &#8211;save bootstrap.<\/p><\/blockquote>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import React from 'react';\n\nconst App = () => (\n  &lt;div className=\"container\">\n    &lt;div className=\"row\">\n      &lt;div className=\"col-6 justify-content-center my-5\">\n        ...\n      &lt;\/div>\n    &lt;\/div>\n  &lt;\/div>\n);\n\nexport default App;<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Building the List Component<\/h2>\n\n\n\n<p>Infinite scroll&nbsp;works great for loading lists of things like photos, status updates, and table data.<\/p>\n\n\n\n<p>In <g class=\"gr_ gr_9 gr-alert gr_gramm gr_inline_cards gr_run_anim Punctuation only-ins replaceWithoutSep\" id=\"9\" data-gr-id=\"9\">this<\/g> tutorial, we&#8217;ll stick to showing a simple list of numbers, but by the end of this tutorial, you&#8217;ll be able to use what you&#8217;ve built for any type of list.<\/p>\n\n\n\n<p>Create a new file called\u00a0<strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">List.js<\/mark><\/strong>\u00a0inside of the src directory, and fill it with the following code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import React, { useState } from 'react';\n\nconst List = () => {\n  const [listItems, setListItems] = useState(Array.from(Array(30).keys(), n => n + 1));\n  \n  return (\n    &lt;>\n      &lt;ul className=\"list-group mb-2\">\n        {listItems.map(listItem => &lt;li className=\"list-group-item\">List Item {listItem}&lt;\/li>)}\n      &lt;\/ul>\n    &lt;\/>\n  );\n};\n\nexport default List;<\/code><\/pre>\n\n\n\n<p>We do a few things using the code above:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Importing React and the new  <a href=\"http:\/\/upmostly.com\/tutorials\/simplifying-react-state-and-the-usestate-hook\">useState hook<\/a>.<\/li><li>Defining a new stateful functional component called <strong>List<\/strong>.<\/li><li>Instantiating a new variable called <strong>listItems<\/strong>, and a new setter function called <strong>setListItems<\/strong> with the help of our new useState hook.<\/li><li>Setting the initial value of listItems to an Array filled with 30 values from 1 to 30.<\/li><li>Finally, returning some HTML which displays an unordered list, loops through listItems and displayed a &lt;li&gt; tag with the value inside for every item in the listItems array.<\/li><\/ul>\n\n\n\n<p><em>Phew,<\/em>&nbsp;we&#8217;re doing  a lot for such a small amount of code! If you haven&#8217;t used React Hooks before, check out our <a rel=\"noreferrer noopener\" aria-label=\"Phew, that was a lot with such a small amount of code. If you haven&#039;t used React Hooks before, check out our Simple Introduction to React Hooks. (opens in a new tab)\" href=\"http:\/\/upmostly.com\/tutorials\/react-hooks-simple-introduction\/\" target=\"_blank\">Simple Introduction to React Hooks<\/a>.<\/p>\n\n\n\n<p>We need to use our new List component Before we see it in action.<\/p>\n\n\n\n<p>Jump back to\u00a0<strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">App.js<\/mark><\/strong>\u00a0and import the List component at the top of the file. Then, declare it in the\u00a0<strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">App.js<\/mark><\/strong>\u00a0return function.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import React from 'react';\nimport List from '.\/List';\n\nconst App = () => (\n  &lt;div className=\"container\">\n    &lt;div className=\"row\">\n      &lt;div className=\"col-6 justify-content-center my-5\">\n        &lt;List \/>\n      &lt;\/div>\n    &lt;\/div>\n  &lt;\/div>\n);\n\nexport default App;<\/code><\/pre>\n\n\n\n<p>Save your files, jump over to your app running in the browser and you should see a brand new list showing 30 items.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"570\" height=\"418\" src=\"http:\/\/upmostly.com\/wp-content\/uploads\/list-component-infinite-scroll.gif\" alt=\"\" class=\"wp-image-632\"\/><figcaption>Our List component, that doesn&#8217;t really do any infinite scrolling&#8230;yet.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Detecting the Bottom of the Page<\/h2>\n\n\n\n<p>Great! We&#8217;ve got a React List component, but it doesn&#8217;t infinite scroll. So let&#8217;s change that next.<\/p>\n\n\n\n<p>An infinite scroll is triggered when you scroll to the bottom of the page. Therefore, we need to detect that the webpage scrollbar is at the end of the page.<\/p>\n\n\n\n<p>There are two parts to accomplishing that. First, we add an <strong>on scroll <\/strong>event listener to the Window object to call a function called&nbsp;<strong><em>handleScroll<\/em><\/strong> every time the window scrolls.<\/p>\n\n\n\n<p>Add the following to the <strong><mark style=\"background-color:rgba(0, 0, 0, 0)\" class=\"has-inline-color has-vivid-red-color\">List.js<\/mark><\/strong> component:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">import React, { useState, useEffect } from 'react';\n\nconst List = () => {\n  ...\n  useEffect(() => {\n    window.addEventListener('scroll', handleScroll);\n    return () => window.removeEventListener('scroll', handleScroll);\n  }, []);\n  ...\n};\n\nexport default List;<\/code><\/pre>\n\n\n\n<p>In the code above, we import another Hook, the <g class=\"gr_ gr_4 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"4\" data-gr-id=\"4\"><strong><em>useEffect<\/em><\/strong><\/g> hook. This gives us functionality similar to the <strong><em>componentDidMount<\/em><\/strong> and <g class=\"gr_ gr_5 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace replaceWithoutSep\" id=\"5\" data-gr-id=\"5\"><strong><em>componentWillUpdate<\/em><\/strong><\/g> lifecycle methods in&nbsp;<g class=\"gr_ gr_37 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep\" id=\"37\" data-gr-id=\"37\">React<\/g> class components.<\/p>\n\n\n\n<p>Let&#8217;s look at <strong><em>useEffect<\/em><\/strong> a little closer.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-jsx\"><code class=\"language-jsx\"><div><span class=\"token function\">useEffect<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  window<span class=\"token punctuation\">.<\/span><span class=\"token function\">addEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'scroll'<\/span><span class=\"token punctuation\">,<\/span> handleScroll<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> window<span class=\"token punctuation\">.<\/span><span class=\"token function\">removeEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'scroll'<\/span><span class=\"token punctuation\">,<\/span> handleScroll<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>Notice how we use an empty array [] as the second parameter of <g class=\"gr_ gr_10 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"10\" data-gr-id=\"10\"><strong><em>useEffect<\/em><\/strong><\/g>? <\/p>\n\n\n\n<p>That tells the <g class=\"gr_ gr_23 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"23\" data-gr-id=\"23\"><strong><em>useEffect<\/em><\/strong><\/g> function to act like <strong><em>componentDidMount<\/em><\/strong> and only run <g class=\"gr_ gr_53 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"53\" data-gr-id=\"53\">one<\/g> time, when the component first mounts.<\/p>\n\n\n\n<p>The second part to detecting the bottom of the page is to check if the Window object&#8217;s inner height, plus the Document object&#8217;s scrollTop, is equal to the Document&#8217;s offsetHeight.<\/p>\n\n\n\n<p>If it is, then we want to fetch more items to add to our List.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-javascript\"><code class=\"language-javascript\"><div><span class=\"token operator\">...<\/span>\n\n<span class=\"token keyword\">function<\/span> <span class=\"token function\">handleScroll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>window<span class=\"token punctuation\">.<\/span>innerHeight <span class=\"token operator\">+<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>scrollTop <span class=\"token operator\">!==<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>offsetHeight<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>\n  console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'Fetch more list items!'<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span>\n\n<span class=\"token operator\">...<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>Let&#8217;s tie all those two steps together, so our List component will look like this:<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-jsx\"><code class=\"language-jsx\"><div><span class=\"token keyword\">import<\/span> React<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span> useState<span class=\"token punctuation\">,<\/span> useEffect <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">from<\/span> <span class=\"token string\">'react'<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">List<\/span> <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>listItems<span class=\"token punctuation\">,<\/span> setListItems<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useState<\/span><span class=\"token punctuation\">(<\/span>Array<span class=\"token punctuation\">.<\/span><span class=\"token keyword\">from<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">Array<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">30<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">keys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> n <span class=\"token operator\">=><\/span> n <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token function\">useEffect<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n    window<span class=\"token punctuation\">.<\/span><span class=\"token function\">addEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'scroll'<\/span><span class=\"token punctuation\">,<\/span> handleScroll<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> window<span class=\"token punctuation\">.<\/span><span class=\"token function\">removeEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'scroll'<\/span><span class=\"token punctuation\">,<\/span> handleScroll<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token keyword\">function<\/span> <span class=\"token function\">handleScroll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>window<span class=\"token punctuation\">.<\/span>innerHeight <span class=\"token operator\">+<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>scrollTop <span class=\"token operator\">!==<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>offsetHeight<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>\n    console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'Fetch more list items!'<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n\n  <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n      <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>ul<\/span> <span class=\"token attr-name\">className<\/span><span class=\"token attr-value\"><span class=\"token punctuation\">=<\/span><span class=\"token punctuation\">\"<\/span>list-group mb-2<span class=\"token punctuation\">\"<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n        <\/span><span class=\"token punctuation\">{<\/span>listItems<span class=\"token punctuation\">.<\/span><span class=\"token function\">map<\/span><span class=\"token punctuation\">(<\/span>listItem <span class=\"token operator\">=><\/span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>li<\/span> <span class=\"token attr-name\">className<\/span><span class=\"token attr-value\"><span class=\"token punctuation\">=<\/span><span class=\"token punctuation\">\"<\/span>list-group-item<span class=\"token punctuation\">\"<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">List Item <\/span><span class=\"token punctuation\">{<\/span>listItem<span class=\"token punctuation\">}<\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>li<\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><span class=\"token plain-text\">\n      <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>ul<\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n    <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span><\/span><span class=\"token punctuation\">><\/span><\/span>\n  <span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">export<\/span> <span class=\"token keyword\">default<\/span> List<span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Handling the <g class=\"gr_ gr_7 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"7\" data-gr-id=\"7\">isFetching<\/g>&nbsp;State<\/h2>\n\n\n\n<p>Now that we have the scroll detection working, the next step is to  fetch more list items and append them to the end of the listItems array.<\/p>\n\n\n\n<p>Let&#8217;s stop for a moment and think about our List component in terms of its state.<\/p>\n\n\n\n<p>When we scroll to the bottom of the page, List has to know&nbsp;to fetch more list items. Therefore its state changes from <strong>not fetching<\/strong> to <strong>fetching<\/strong>.<\/p>\n\n\n\n<p>As a result, we need to add another state variable to our List component to keep track of that state change. Let&#8217;s call it&nbsp;<strong>isFetching<\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-jsx\"><code class=\"language-jsx\"><div><span class=\"token operator\">...<\/span>\n\n<span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">List<\/span> <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>listItems<span class=\"token punctuation\">,<\/span> setListItems<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useState<\/span><span class=\"token punctuation\">(<\/span>Array<span class=\"token punctuation\">.<\/span><span class=\"token keyword\">from<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">Array<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">30<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">keys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> n <span class=\"token operator\">=><\/span> n <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">,<\/span> setIsFetching<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useState<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  \n  <span class=\"token operator\">...<\/span>\n  \n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>We define a new state variable called <strong><g class=\"gr_ gr_4 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"4\" data-gr-id=\"4\">isFetching<\/g><\/strong>, along with a state setter function called <strong>setIsFetching<\/strong>. Let&#8217;s set the initial value to false because when our web app loads for the first time, the window is scrolled to the top of the page.<\/p>\n\n\n\n<p>Now that we have this new state variable, let&#8217;s modify our&nbsp;<em><strong>handleScroll<\/strong>&nbsp;<\/em>function so that it sets the state of <strong>isFetching<\/strong> to true whenever we scroll to the bottom of the page:<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-javascript\"><code class=\"language-javascript\"><div><span class=\"token keyword\">function<\/span> <span class=\"token function\">handleScroll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>window<span class=\"token punctuation\">.<\/span>innerHeight <span class=\"token operator\">+<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>scrollTop <span class=\"token operator\">!==<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>offsetHeight<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token function\">setIsFetching<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">true<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Fetching More List Items<\/h2>\n\n\n\n<p>Right now we&#8217;re not doing anything with our new isFetching state change. Let&#8217;s change that.<\/p>\n\n\n\n<p>With React Hooks and the <strong><em>useEffect<\/em><\/strong> Hook, we can now listen out for&nbsp;changes in state. Therefore, why don&#8217;t we listen for when <g class=\"gr_ gr_4 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"4\" data-gr-id=\"4\"><strong>isFetching<\/strong><\/g> changes to true and call a function to get more list items?<\/p>\n\n\n\n<p>Add another <strong><em>useEffect<\/em><\/strong> function that listens for a change to<strong> isFetching<\/strong>. We do that by putting <strong>isFetching<\/strong> inside the array that&#8217;s passed to the second parameter to <strong><em>useEffect<\/em><\/strong>.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-jsx\"><code class=\"language-jsx\"><div><span class=\"token function\">useEffect<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>isFetching<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token function\">fetchMoreListItems<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>This effect will call every time <strong>isFetching<\/strong> changes state. That includes when it&#8217;s false. We don&#8217;t want that, so we add a conditional at the top which returns whenever<strong> isFetching<\/strong> is false.<\/p>\n\n\n\n<p>Finally, let&#8217;s add the function to fetch more list items.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-javascript\"><code class=\"language-javascript\"><div><span class=\"token operator\">...<\/span>\n\n<span class=\"token keyword\">function<\/span> <span class=\"token function\">fetchMoreListItems<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token function\">setTimeout<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n    <span class=\"token function\">setListItems<\/span><span class=\"token punctuation\">(<\/span>prevState <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">[<\/span><span class=\"token operator\">...<\/span>prevState<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">...<\/span>Array<span class=\"token punctuation\">.<\/span><span class=\"token keyword\">from<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">Array<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">20<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">keys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> n <span class=\"token operator\">=><\/span> n <span class=\"token operator\">+<\/span> prevState<span class=\"token punctuation\">.<\/span>length <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token function\">setIsFetching<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">2000<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span>\n\n<span class=\"token operator\">...<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>For demo purposes, I&#8217;ve wrapped the setter inside a timeout to simulate two seconds of loading time that you might experience from a real-world application.<\/p>\n\n\n\n<p>Once two seconds elapses, we call setListItems, and add another 20 listItems to the array. Afterwards, we set&nbsp;<g class=\"gr_ gr_4 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"4\" data-gr-id=\"4\"><g class=\"gr_ gr_4 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"4\" data-gr-id=\"4\">isFetching<\/g><\/g> to false.<\/p>\n\n\n\n<p>Last but not least, let&#8217;s add a label underneath the list to tell the user that we&#8217;re fetching more items when <g class=\"gr_ gr_3 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"3\" data-gr-id=\"3\">isFetching<\/g> is true.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-jsx\"><code class=\"language-jsx\"><div><span class=\"token operator\">...<\/span>\n\n<span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span>\n  <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n    <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>ul<\/span> <span class=\"token attr-name\">className<\/span><span class=\"token attr-value\"><span class=\"token punctuation\">=<\/span><span class=\"token punctuation\">\"<\/span>list-group mb-2<span class=\"token punctuation\">\"<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n      <\/span><span class=\"token punctuation\">{<\/span>listItems<span class=\"token punctuation\">.<\/span><span class=\"token function\">map<\/span><span class=\"token punctuation\">(<\/span>listItem <span class=\"token operator\">=><\/span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>li<\/span> <span class=\"token attr-name\">className<\/span><span class=\"token attr-value\"><span class=\"token punctuation\">=<\/span><span class=\"token punctuation\">\"<\/span>list-group-item<span class=\"token punctuation\">\"<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">List Item <\/span><span class=\"token punctuation\">{<\/span>listItem<span class=\"token punctuation\">}<\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>li<\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><span class=\"token plain-text\">\n    <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>ul<\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n    <\/span><span class=\"token punctuation\">{<\/span>isFetching <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token string\">'Fetching more list items...'<\/span><span class=\"token punctuation\">}<\/span><span class=\"token plain-text\">\n  <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span><\/span><span class=\"token punctuation\">><\/span><\/span>\n<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token operator\">...<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>Save your component, jump back to the app running in your browser and take it for a spin!<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"570\" height=\"200\" src=\"http:\/\/upmostly.com\/wp-content\/uploads\/infinite-scroll-finish.gif\" alt=\"\" class=\"wp-image-659\"\/><figcaption>Our finished React infinite scroll component<\/figcaption><\/figure>\n\n\n\n<p>You can either stop here or continue reading to see how we can simplify our React infinite scroll component by writing a custom React Hook to handle the logic for us.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Simplifying Infinite Scroll with a Custom React Hook<\/h2>\n\n\n\n<p>Although our Infinite Scroll component is working great, it&#8217;s not the best implementation.<\/p>\n\n\n\n<p>Imagine you&#8217;re building a real-world web app with multiple components that use infinite scroll. For example, a list of users, a list of user&#8217;s photos, and a&nbsp;<g class=\"gr_ gr_31 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep\" id=\"31\" data-gr-id=\"31\">list<\/g> of status updates&#8230;<\/p>\n\n\n\n<p>We&#8217;d have to include the infinite scroll logic inside each of those components. That&#8217;s bad, because:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>We&#8217;re not staying DRY (Don&#8217;t Repeat Yourself)<\/li><li>We&#8217;re wasting time re-writing code that&#8217;s already been written<\/li><li>We&#8217;re not making it easy on ourselves if we want to change the infinite scroll logic. We&#8217;d have to change it in multiple places.<\/li><\/ul>\n\n\n\n<p>But, what if we didn&#8217;t have to duplicate that code?<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>React Hooks are a new addition since React 16.8. Writing custom React Hooks allow us to write functions to share common stateful logic between multiple components.<\/p><\/blockquote>\n\n\n\n<p>In other words, we can pull out all of the infinite scroll logic and put it inside a custom React Hook called <strong><g class=\"gr_ gr_3 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"3\" data-gr-id=\"3\">useInfiniteScroll<\/g><\/strong>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">The <g class=\"gr_ gr_13 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"13\" data-gr-id=\"13\">useInfiniteScroll<\/g>&nbsp;React Hook<\/h2>\n\n\n\n<p>Create a new file called <strong><span class=\"has-inline-color has-vivid-red-color\">useInfiniteScroll.js<\/span><\/strong>. We&#8217;re going to define a new function called <strong><em>useInfiniteScroll<\/em><\/strong> inside of it, like so:<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">useInfiniteScroll.js<\/div><pre class=\"language-javascript\"><code class=\"language-javascript\"><div><span class=\"token keyword\">import<\/span> <span class=\"token punctuation\">{<\/span> useState <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">from<\/span> <span class=\"token string\">'react'<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">useInfiniteScroll<\/span> <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span>callback<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">,<\/span> setIsFetching<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useState<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">export<\/span> <span class=\"token keyword\">default<\/span> useInfiniteScroll<span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>Our custom React Hook takes one parameter, a function called&nbsp;<strong><g class=\"gr_ gr_4 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar only-ins replaceWithoutSep\" id=\"4\" data-gr-id=\"4\">callback<\/g><\/strong>. <\/p>\n\n\n\n<p>We want our Hook to call whatever function we pass into the callback parameter after it has detected that the scrollbar is at the bottom of the page.<\/p>\n\n\n\n<p>Let&#8217;s remove all of the logic we wrote previously in <strong><span class=\"has-inline-color has-vivid-red-color\">List.js<\/span><\/strong>, and put it inside the new&nbsp;<g class=\"gr_ gr_3 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"3\" data-gr-id=\"3\"><strong><em>useInfiniteScroll<\/em><\/strong><\/g> Hook:<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">useInfiniteScroll.js<\/div><pre class=\"language-javascript\"><code class=\"language-javascript\"><div><span class=\"token keyword\">import<\/span> <span class=\"token punctuation\">{<\/span> useState<span class=\"token punctuation\">,<\/span> useEffect <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">from<\/span> <span class=\"token string\">'react'<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">useInfiniteScroll<\/span> <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span>callback<span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">,<\/span> setIsFetching<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useState<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token function\">useEffect<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n    window<span class=\"token punctuation\">.<\/span><span class=\"token function\">addEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'scroll'<\/span><span class=\"token punctuation\">,<\/span> handleScroll<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> window<span class=\"token punctuation\">.<\/span><span class=\"token function\">removeEventListener<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'scroll'<\/span><span class=\"token punctuation\">,<\/span> handleScroll<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token function\">useEffect<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token operator\">!<\/span>isFetching<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token function\">callback<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n      console<span class=\"token punctuation\">.<\/span><span class=\"token function\">log<\/span><span class=\"token punctuation\">(<\/span><span class=\"token string\">'called back'<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token keyword\">function<\/span> <span class=\"token function\">handleScroll<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n    <span class=\"token keyword\">if<\/span> <span class=\"token punctuation\">(<\/span>window<span class=\"token punctuation\">.<\/span>innerHeight <span class=\"token operator\">+<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>scrollTop <span class=\"token operator\">!==<\/span> document<span class=\"token punctuation\">.<\/span>documentElement<span class=\"token punctuation\">.<\/span>offsetHeight <span class=\"token operator\">||<\/span> isFetching<span class=\"token punctuation\">)<\/span> <span class=\"token keyword\">return<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token function\">setIsFetching<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">true<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n\n  <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">,<\/span> setIsFetching<span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">export<\/span> <span class=\"token keyword\">default<\/span> useInfiniteScroll<span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>Using a custom React Hook has <strong>cut down the code in our List component by nearly half.<\/strong><\/p>\n\n\n\n<p>Our very skinny List component now looks like this:<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">List.js<\/div><pre class=\"language-jsx\"><code class=\"language-jsx\"><div><span class=\"token keyword\">import<\/span> React<span class=\"token punctuation\">,<\/span> <span class=\"token punctuation\">{<\/span> useState <span class=\"token punctuation\">}<\/span> <span class=\"token keyword\">from<\/span> <span class=\"token string\">'react'<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token keyword\">import<\/span> useInfiniteScroll <span class=\"token keyword\">from<\/span> <span class=\"token string\">\".\/useInfiniteScroll\"<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">const<\/span> <span class=\"token function-variable function\">List<\/span> <span class=\"token operator\">=<\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>listItems<span class=\"token punctuation\">,<\/span> setListItems<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useState<\/span><span class=\"token punctuation\">(<\/span>Array<span class=\"token punctuation\">.<\/span><span class=\"token keyword\">from<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">Array<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">30<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">keys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> n <span class=\"token operator\">=><\/span> n <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">,<\/span> setIsFetching<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useInfiniteScroll<\/span><span class=\"token punctuation\">(<\/span>fetchMoreListItems<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n\n  <span class=\"token keyword\">function<\/span> <span class=\"token function\">fetchMoreListItems<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token punctuation\">{<\/span>\n    <span class=\"token function\">setTimeout<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span> <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">{<\/span>\n      <span class=\"token function\">setListItems<\/span><span class=\"token punctuation\">(<\/span>prevState <span class=\"token operator\">=><\/span> <span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">[<\/span><span class=\"token operator\">...<\/span>prevState<span class=\"token punctuation\">,<\/span> <span class=\"token operator\">...<\/span>Array<span class=\"token punctuation\">.<\/span><span class=\"token keyword\">from<\/span><span class=\"token punctuation\">(<\/span><span class=\"token function\">Array<\/span><span class=\"token punctuation\">(<\/span><span class=\"token number\">20<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">.<\/span><span class=\"token function\">keys<\/span><span class=\"token punctuation\">(<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">,<\/span> n <span class=\"token operator\">=><\/span> n <span class=\"token operator\">+<\/span> prevState<span class=\"token punctuation\">.<\/span>length <span class=\"token operator\">+<\/span> <span class=\"token number\">1<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">]<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n      <span class=\"token function\">setIsFetching<\/span><span class=\"token punctuation\">(<\/span><span class=\"token boolean\">false<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n    <span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">,<\/span> <span class=\"token number\">2000<\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n  <span class=\"token punctuation\">}<\/span>\n\n  <span class=\"token keyword\">return<\/span> <span class=\"token punctuation\">(<\/span>\n    <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n      <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>ul<\/span> <span class=\"token attr-name\">className<\/span><span class=\"token attr-value\"><span class=\"token punctuation\">=<\/span><span class=\"token punctuation\">\"<\/span>list-group mb-2<span class=\"token punctuation\">\"<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n        <\/span><span class=\"token punctuation\">{<\/span>listItems<span class=\"token punctuation\">.<\/span><span class=\"token function\">map<\/span><span class=\"token punctuation\">(<\/span>listItem <span class=\"token operator\">=><\/span> <span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;<\/span>li<\/span> <span class=\"token attr-name\">className<\/span><span class=\"token attr-value\"><span class=\"token punctuation\">=<\/span><span class=\"token punctuation\">\"<\/span>list-group-item<span class=\"token punctuation\">\"<\/span><\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">List Item <\/span><span class=\"token punctuation\">{<\/span>listItem<span class=\"token punctuation\">}<\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>li<\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">}<\/span><span class=\"token plain-text\">\n      <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span>ul<\/span><span class=\"token punctuation\">><\/span><\/span><span class=\"token plain-text\">\n      <\/span><span class=\"token punctuation\">{<\/span>isFetching <span class=\"token operator\">&amp;&amp;<\/span> <span class=\"token string\">'Fetching more list items...'<\/span><span class=\"token punctuation\">}<\/span><span class=\"token plain-text\">\n    <\/span><span class=\"token tag\"><span class=\"token tag\"><span class=\"token punctuation\">&lt;\/<\/span><\/span><span class=\"token punctuation\">><\/span><\/span>\n  <span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span>\n<span class=\"token punctuation\">}<\/span><span class=\"token punctuation\">;<\/span>\n\n<span class=\"token keyword\">export<\/span> <span class=\"token keyword\">default<\/span> List<span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<p>Notice that we&#8217;re importing <strong><g class=\"gr_ gr_3 gr-alert gr_spell gr_inline_cards gr_disable_anim_appear ContextualSpelling ins-del multiReplace\" id=\"3\" data-gr-id=\"3\">useInfiniteScroll<\/g><\/strong> at the top of the file, and declaring it under the listItems and setListItems state.<\/p>\n\n\n\n<p>Using our infinite scroll hook custom React Hook is one line. All we have to do is pass it the function that we want it to run. In our case, it&#8217;s the fetchMoreListItems function.<\/p>\n\n\n\n<div class=\"wp-block-cgb-block-codeplus\"><div class=\"upmostly-block better-code-block\"><div class=\"dark\"><div class=\"code-editor-header\">useInfiniteScroll.js<\/div><pre class=\"language-javascript\"><code class=\"language-javascript\"><div><span class=\"token keyword\">const<\/span> <span class=\"token punctuation\">[<\/span>isFetching<span class=\"token punctuation\">,<\/span> setIsFetching<span class=\"token punctuation\">]<\/span> <span class=\"token operator\">=<\/span> <span class=\"token function\">useInfiniteScroll<\/span><span class=\"token punctuation\">(<\/span>fetchMoreListItems<span class=\"token punctuation\">)<\/span><span class=\"token punctuation\">;<\/span><\/div><\/code><\/pre><\/div><\/div><\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Wrapping Up<\/h2>\n\n\n\n<p>Well, there you have it. An infinite scroll list component built entirely using React Hooks. <\/p>\n\n\n\n<p>We even got an added bonus of writing a custom React Hook to make our component nice and clean.<\/p>\n\n\n\n<p>The entire codebase  is over on our <a aria-label=\"The entire codebase  is over on our GitHub  repository for this tutorial. (opens in a new tab)\" href=\"https:\/\/github.com\/Upmostly\/react-hooks-infinite-scroll\" target=\"_blank\" rel=\"noreferrer noopener\">GitHub repository for this tutorial<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Today we&#8217;re going to dive deeper into React development and learn how to build an infinite scroll component in React using React Hooks. Let&#8217;s get started!<\/p>\n","protected":false},"author":8,"featured_media":679,"comment_status":"open","ping_status":"open","sticky":false,"template":"post-tutorial-new.php","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[33,40,4,38,35],"class_list":["post-613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tutorials","tag-beginner-react-tutorials","tag-popular-tutorials","tag-react","tag-react-components","tag-react-hooks"],"acf":[],"_links":{"self":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts\/613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/users\/8"}],"replies":[{"embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/comments?post=613"}],"version-history":[{"count":4,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts\/613\/revisions"}],"predecessor-version":[{"id":13065,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/posts\/613\/revisions\/13065"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/media\/679"}],"wp:attachment":[{"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/media?parent=613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/categories?post=613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/upmostly.com\/wp-json\/wp\/v2\/tags?post=613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}