<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Apestein</title>
    <description>The latest articles on DEV Community by Apestein (@apestein).</description>
    <link>https://dev.to/apestein</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1009612%2Fcb0cf10a-6411-4279-a6e0-649d8bbf06fe.png</url>
      <title>DEV Community: Apestein</title>
      <link>https://dev.to/apestein</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/apestein"/>
    <language>en</language>
    <item>
      <title>Complete guide for infinite scroll feature in React🧑‍🍳</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Sat, 14 Dec 2024 16:07:48 +0000</pubDate>
      <link>https://dev.to/apestein/complete-guide-for-infinite-scroll-feature-in-react-a5n</link>
      <guid>https://dev.to/apestein/complete-guide-for-infinite-scroll-feature-in-react-a5n</guid>
      <description>&lt;p&gt;Intended to be a complete guide to infinite scroll in React. Nothing to install, just copy/paste and customize. Examples with Next.js / Tailwind / Tanstack Query / and Tanstack Virtual. This will be the best repo to reference when implementing an infinite scroll feature in React. Infinite scroll feature can be quite hard, especially for bi-directional scroll and virtual scroll (for very large list) support. I hope this repo can save people some time, let me know what yall think.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/Apestein/better-react-infinite-scroll" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://stackblitz.com/~/github.com/Apestein/better-react-infinite-scroll" rel="noopener noreferrer"&gt;Demo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>webdev</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>What is Edge compute? Everything you need to know🧐</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Sat, 16 Sep 2023 14:00:00 +0000</pubDate>
      <link>https://dev.to/apestein/what-is-edge-compute-everything-you-need-to-know-3368</link>
      <guid>https://dev.to/apestein/what-is-edge-compute-everything-you-need-to-know-3368</guid>
      <description>&lt;h2&gt;
  
  
  These are the primary edge compute providers.
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Cloudflare Workers&lt;/li&gt;
&lt;li&gt;Deno Deploy &lt;/li&gt;
&lt;li&gt;Fly.io&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;There is also AWS lambada@edge which is just lambda function at edge locations, however the runtime is still node and suffers from cold start so it's not worth talking about. All others edge providers just resell edge functions from these providers. For example, Vercel edge is just Cloudflare workers under the hood. Netlify and Supabase edge is just Deno Deploy.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  First of all, what exactly is edge compute?
&lt;/h2&gt;

&lt;p&gt;"Edge" can refer to either edge locations(servers close to users) or edge runtime or both. Above I mentioned, AWS's lambda@edge is just node runtime at edge locations. Edge compute offers better performance, faster loads, and cheaper cost when compared to regular serverless functions like lambda/google functions. It's not controversial to say Edge will be the future of cloud compute.&lt;/p&gt;

&lt;h2&gt;
  
  
  There are 2 category of edge providers.
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Edge functions: Cloudflare Workers &amp;amp; Deno Deploy

&lt;ul&gt;
&lt;li&gt;Cloudflare Workers and Deno Deploy run on V8 isolate(like your browser) and have their own unique runtime with a limited set of web APIs. These edge functions have zero cold start time. Each instant is like opening a new browser tab and can only handle one request. Functions auto-scale up and down and scale to zero by default. To deploy to edge runtime you must only use supported web APIs. Some tools don't support edge runtime so keep that in mind, prisma for example can't run on edge.
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Edge containers: Fly.io

&lt;ul&gt;
&lt;li&gt;Fly.io run actual containers. This gives you much more control. You can pick your runtime, read/write to the file system, and even have an embedded SQLite database for insane performance. Containers are much more resource efficient and can handle many request concurrently. Fly's container auto-scale up and down like serverless functions. Fly's container does not scale to zero by default but can be opt-in to do so. They claim to have cold start time of only 100-200ms which is similar to lambda functions. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In general, functions will be cheaper early on while container will become more and more cost efficient as you scale up. Containers can perform many more actions than functions but also require more manual configuration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Actually, I lied.
&lt;/h2&gt;

&lt;p&gt;Edge does &lt;strong&gt;NOT&lt;/strong&gt; always give you better performance. This depends upon where your &lt;a href="https://vercel.com/docs/functions/edge-functions#regional-edge-function-invocation"&gt;database&lt;/a&gt; is located. To always get better performance, you need to use an "Edge database". It's exactly as it sounds, distributed database around the globe. Now your edge functions/containers will uses the nearest edge database. The most popular fully-managed edge database is &lt;a href="https://turso.tech/"&gt;Turso&lt;/a&gt;. There is also &lt;a href="https://fly.io/docs/litefs/"&gt;LiteFS&lt;/a&gt; from Fly.io which is an embedded database. Meaning it runs in the same container as your app, this gives you INSANELY low latency, however it's not fully-managed so keep that in mind. Practically speaking, any edge database has to use SQLite. That is because it is extremely cheap to replicate compared to mySQL/PostgreSQL. It's not impossible but just not practical. If you are not using edge database, it is recommended to limit your edge to a single region closest to your database. Technically, it's no longer "edge" but you will still benefit from no cold start and lower cost.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Looking to learn Next.js 13 app router using the latest cutting-edge tech stack? Check out my &lt;a href="https://github.com/Apestein/nextflix"&gt;project&lt;/a&gt;. It runs 100% on edge btw.&lt;/em&gt; &lt;/p&gt;

&lt;h3&gt;
  
  
  References
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://fly.io/blog/the-serverless-server/"&gt;1&lt;/a&gt;&lt;br&gt;
&lt;a href="https://fauna.com/blog/comparison-faas-providers"&gt;2&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Like this article? Follow me on &lt;a href="https://twitter.com/Apestein_Dev"&gt;X&lt;/a&gt; (formerly Twitter) for tech advice and hot takes.
&lt;/h2&gt;

</description>
      <category>webdev</category>
      <category>cloud</category>
      <category>serverless</category>
    </item>
    <item>
      <title>Bleeding-edge Project Using Everything New In Next.js 13📚</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Tue, 12 Sep 2023 01:25:58 +0000</pubDate>
      <link>https://dev.to/apestein/bleeding-edge-project-using-everything-new-in-nextjs-13-4mlg</link>
      <guid>https://dev.to/apestein/bleeding-edge-project-using-everything-new-in-nextjs-13-4mlg</guid>
      <description>&lt;p&gt;Project using bleeding-edge stack. Drizzle ORM + Neon postgres + Clerk auth + Shadcn/ui + everything new in Next.js 13 (server components, server actions, streaming ui, parallel routes, intercepting routes). Fully edge runtime deployed. I wrote a breakdown and talked about some tricky / difficult things while building this project. This will be a good reference project for people looking to learn Next.js app router. Project uses 100% server actions and include features such as ability to search show catalog, SaaS subscription service with Stripe, optimistic update, and infinite scrolling.&lt;/p&gt;

&lt;p&gt;Repo: &lt;a href="https://github.com/Apestein/nextflix"&gt;https://github.com/Apestein/nextflix&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Live: &lt;a href="https://nextflix-blush.vercel.app/"&gt;https://nextflix-blush.vercel.app/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>How to Publish to NPM the Right Way</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Sun, 11 Jun 2023 03:42:50 +0000</pubDate>
      <link>https://dev.to/apestein/how-to-publish-to-npm-the-right-way-2pd7</link>
      <guid>https://dev.to/apestein/how-to-publish-to-npm-the-right-way-2pd7</guid>
      <description>&lt;h2&gt;
  
  
  &lt;a href="https://github.com/Apestein/react-lib-starter"&gt;React Library Starter&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Starter template for your next react typescript library. Complete with changeset, tsup, and tailwind with prettier-plugin. Publish to npm the right and easy way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to npm and create your access token with type of "Publish" or "Automation". Copy the token.&lt;/li&gt;
&lt;li&gt;Go to your repo, click on "Settings" =&amp;gt; "Secrets and variables" =&amp;gt; "Actions" =&amp;gt; "New repository secret" then create token named "NPM_TOKEN" and paste token from step 1.&lt;/li&gt;
&lt;li&gt;Go to your repo, click on "Settings" =&amp;gt; "Actions" =&amp;gt; "General" then make sure Workflow permissions is set to "Read and write permissions" and check "Allow Github Actions to create and approve pull requests."&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  How to use
&lt;/h3&gt;

&lt;p&gt;Create your package in package/index. Then import and test from src/App.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;pnpm changeset&lt;/code&gt; then push to your Github and workflow will create a PR for you to merge. Once you merge, your package will be automatically published to npm.&lt;/p&gt;

&lt;p&gt;Or run &lt;code&gt;pnpm release&lt;/code&gt; to publish directly from your command line. Remember to login with &lt;code&gt;npm login&lt;/code&gt; and update version property in package.json.&lt;/p&gt;

&lt;h3&gt;
  
  
  Video tutorial from &lt;a href="https://www.youtube.com/watch?v=eh89VE3Mk5g"&gt;Matt Pocock&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  If you find this useful, please star this repo on &lt;a href="https://github.com/Apestein/react-lib-starter"&gt;Github&lt;/a&gt;. Also, follow me on &lt;a href="https://twitter.com/Apestein_Dev"&gt;Twitter&lt;/a&gt; for tech advise and hot takes.
&lt;/h3&gt;

&lt;p&gt;PS: Currently looking for a new position, hire me. Check my profile for info.&lt;/p&gt;

</description>
      <category>tutorial</category>
      <category>react</category>
      <category>npm</category>
    </item>
    <item>
      <title>Easy React Infinite Scroll👌</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Sat, 10 Jun 2023 00:01:13 +0000</pubDate>
      <link>https://dev.to/apestein/easy-react-infinite-scroll-367h</link>
      <guid>https://dev.to/apestein/easy-react-infinite-scroll-367h</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I had a hard time implementing a react infinite scroll feature so I decided to make an npm package to make it super simple. If you have ever tried to implement a react infinite scroll feature you might have seen &lt;a href="https://www.npmjs.com/package/react-infinite-scroll-component"&gt;react-infinite-scroll-component&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/react-infinite-scroller"&gt;react-finite-scroller&lt;/a&gt;. The problem with these packages are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;They are large, which makes them hard to customize.&lt;/li&gt;
&lt;li&gt;Written as class component, also hard to customize.&lt;/li&gt;
&lt;li&gt;Uses the event listener on the scroll event which is not performant. Mine uses the modern intersection observer API.
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Better React Infinite Scroll
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/better-react-infinite-scroll"&gt;NPM&lt;/a&gt;&lt;br&gt;
&lt;a href="https://better-react-infinite-scroll.vercel.app/"&gt;Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Apestein/better-react-infinite-scroll/blob/main/src/App.tsx"&gt;Source Code&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Install or just copy and paste...
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;InfiniteScrollProps&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentPropsWithRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;div&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;any&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;loadingMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;endingMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;InfiniteScrollProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;loadingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;endingMessage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observerTarget&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;IntersectionObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;isIntersecting&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;threshold&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;unobserve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;observerTarget&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;observerTarget&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; &lt;span class="na"&gt;overflowAnchor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;none&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;observerTarget&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;loadingMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;endingMessage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  How to use: normal scroll
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;better-react-infinite-scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt;
    &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;loadingMessage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="nx"&gt;endingMessage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;beginning&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;))}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/InfiniteScroller&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  How to use: inverse scroll
&lt;/h2&gt;

&lt;p&gt;For inverse scroll, use flex-direction: column-reverse. Scoller height must be defined. Here we use tailwind flex-1 (flex: 1 1 0%) but height: 300px would also work for example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;better-react-infinite-scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex h-screen flex-col&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt;
      &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;loadingMessage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="nx"&gt;endingMessage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;beginning&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;flex flex-1 flex-col-reverse overflow-auto&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;elements&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/InfiniteScroller&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Full example with tRPC and React Query (TanStack Query)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;better-react-infinite-scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;//if using with tRPC&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hasNextPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getAll&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;useInfiniteQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getNextPageParam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastPage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lastPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextCursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;//if using with React Query (TanStack)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;hasNextPage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useInfiniteQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;projects&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;queryFn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fetchProjects&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;getNextPageParam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;lastPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nextCursor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;aggregatePosts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;combinedPosts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;shallowCopy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;shallowCopy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;combinedPosts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;shallowCopy&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InfiniteScroller&lt;/span&gt;
      &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;loadingMessage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Loading&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;      &lt;span class="nx"&gt;endingMessage&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;beginning&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;}
&lt;/span&gt;    &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;aggregatePosts&lt;/span&gt;&lt;span class="p"&gt;()?.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/li&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/InfiniteScroller&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://trpc.io/docs/client/react/useInfiniteQuery"&gt;tRPC docs&lt;/a&gt;&lt;br&gt;
&lt;a href="https://tanstack.com/query/v4/docs/react/guides/infinite-queries"&gt;React Query docs&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  If you find this useful, please star this repo on &lt;a href="https://github.com/Apestein/better-react-infinite-scroll"&gt;Github&lt;/a&gt;. Also, follow me on &lt;a href="https://twitter.com/Apestein_Dev"&gt;Twitter&lt;/a&gt; for tech advise and hot takes.
&lt;/h2&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Top 5 Tailwind Component Libraries</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Fri, 26 May 2023 00:52:50 +0000</pubDate>
      <link>https://dev.to/apestein/top-5-tailwind-component-libraries-m0c</link>
      <guid>https://dev.to/apestein/top-5-tailwind-component-libraries-m0c</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Why might you want to use a tailwind based component library instead of a something like MUI, Chakra UI, and Mantine? If you are using tailwind, it is best to use a tailwind based component library where you can customize the components with tailwind directly.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a href="https://daisyui.com/"&gt;DaisyUI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Daisy gives you special classes like "btn", "card", etc. These special classes are a combination of other tailwind utility classes. These classes have low specificity so you can easily override them like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"btn bg-blue-500"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Default&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some people might not agree that I ranked Daisy so low but in my opinion Daisy has some problems:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;It does not look professional, the colors are too flamboyant, can you customize it to be more professional? Sure. But it's not professional looking right out the box.&lt;/li&gt;
&lt;li&gt;It abstracts how components are created. Basically, when you use the special classes like "btn", you have no idea which tailwind utility classes they are composed of. This is not ideal for learning and customizing, therefore I prefer none-abstracting component libraries.&lt;/li&gt;
&lt;li&gt;Components are pure html/css. This just means daisy components are limited in what they can do. Components with Javascript are much more powerful by comparison.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  4. &lt;a href="https://flowbite.com/"&gt;Flowbite&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Important note, Flowbite has two version, regular Flowbite and &lt;a href="https://flowbite-react.com/"&gt;Flowbite React&lt;/a&gt;. I will only be talking about regular Flowbite and not Flowbite react as I think it's not good. Flowbite is a copy and paste library, meaning you don't need to install anything, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Default&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Problem as you can see is that it doesn't support React. So you will need to change "class" to "className" with every paste. Also, it's another pure html/css component library.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. &lt;a href="https://wind-ui.com/"&gt;WindUI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Like Flowbite but better. This component library does support React so just copy and paste. It also looks much more aesthetic in my opinion. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://www.material-tailwind.com/"&gt;Material Tailwind&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Very slick and professional looking component library. Unlike the others component libraries before, it does have Javascript and is more powerful in terms of what it can do.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@material-tailwind/react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Example&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt; &lt;span class="nx"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;sm&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;rounded-lg&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Button&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Button&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And as you can see, you can easily customize the component by writing tailwind utility classes directly. The only "Con" left is abstraction. You cannot see how the component was created and with what tailwind classes. &lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a href="https://ui.shadcn.com/"&gt;shadcn/ui&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A copy and paste component library. Similar to Material Tailwind except with zero abstraction. You can see all the code making up a component and see all the associated CSS. Fully and easily customize all parts of the components. The only possible "Con" is that it's less beginner friendly. Because it gives you complete low level control it might be more intimating for less experienced users.     &lt;/p&gt;

&lt;h2&gt;
  
  
  Honorable Mention: &lt;a href="https://tailwindui.com/"&gt;TailwindUI&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Official component library from Tailwind Labs. Very good, but is 300$.&lt;/p&gt;

&lt;p&gt;PS: Follow me on Twitter for tech hot takes&lt;br&gt;
&lt;a href="https://twitter.com/Apestein_Dev"&gt;https://twitter.com/Apestein_Dev&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tailwindcss</category>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
    </item>
    <item>
      <title>This Tailwind Twitter Drama Could Have Been Avoided😓</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Sun, 22 Jan 2023 01:00:22 +0000</pubDate>
      <link>https://dev.to/apestein/this-tailwind-twitter-drama-could-have-been-avoided-23cb</link>
      <guid>https://dev.to/apestein/this-tailwind-twitter-drama-could-have-been-avoided-23cb</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsuf9qwe772ioly7w2pu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqsuf9qwe772ioly7w2pu.png" alt="Tweet" width="603" height="654"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So this is the tweet that caused the massive Tailwind drama on twitter recently. All because @shadcn decided to breakup tailwind classes and group them into different lines. All because @shadcn didn't know about &lt;a href="https://tailwindcss.com/blog/automatic-class-sorting-with-prettier" rel="noopener noreferrer"&gt;Prettier plugin for Tailwind CSS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this plugin, Tailwind classes will be intelligently sorted with every save. Seriously I don't know why they just don't include this plugin with Tailwind by default. Here is the quick summary:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The actual order of the different utilities is loosely based on the box model, and tries to put high impact classes that affect the layout at the beginning and decorative classes at the end, while also trying to keep related utilities together.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Tailwind is honestly magic people. If you haven't tried it, you're missing out. And if you have tried it but didn't like it, try it a little longer. &lt;/p&gt;

</description>
      <category>ai</category>
      <category>chatgpt</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Intuitive Vim Keybinding For VScode😏</title>
      <dc:creator>Apestein</dc:creator>
      <pubDate>Thu, 19 Jan 2023 01:48:57 +0000</pubDate>
      <link>https://dev.to/apestein/intuitive-vim-keybinding-for-vscode-2ga0</link>
      <guid>https://dev.to/apestein/intuitive-vim-keybinding-for-vscode-2ga0</guid>
      <description>&lt;p&gt;&lt;strong&gt;Is vim hard to pick up? Well, not anymore with my intuitive keybindings for VScode vim extension.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "vim.normalModeKeyBindings": [
    {
      "before": ["k"],
      "commands": ["cursorDown"]
    },
    {
      "before": ["i"],
      "commands": ["cursorUp"]
    },
    {
      "before": ["j"],
      "commands": ["cursorLeft"]
    },
    {
      "before": ["l"],
      "commands": ["cursorRight"]
    },
    {
      "before": ["h"],
      "after": ["&amp;lt;insert&amp;gt;"]
    },
  ],
  "vim.visualModeKeyBindingsNonRecursive": [
    {
      "before": ["h"],
      "after": ["i"]
    },
    {
      "before": ["i"],
      "after": ["k"]
    },
    {
      "before": ["k"],
      "after": ["j"]
    },
    {
      "before": ["j"],
      "after": ["h"]
    },
    {
      "before": ["h"],
      "after": ["i"]
    }
  ],
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now "i" is up, "k" is down, "j" is left, "l" is right and "h" is insert. If you have played any pc games, this movement will feel right at home.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Now some more tips to increase your vim productivity&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Rebind capslock to escape. For linux you can use "tweaks" from the Ubuntu Store and for windows you can use "powertoys".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rdn91eobzuwy7tg1x7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7rdn91eobzuwy7tg1x7r.png" alt="Image description"&gt;&lt;/a&gt;&lt;br&gt;
After settings capslock as additional escape in "Tweaks" you must then change keybinding in vscode like below, if you do it in the wrong order it will not work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
{
    "key": "capslock",
    "command": "extension.vim_escape",
    "when": "editorTextFocus &amp;amp;&amp;amp; vim.active &amp;amp;&amp;amp; !inDebugRepl"
  },
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Rebind Alt + i/k/j/l to navigate in insert mode. Without it, you must exit insert mode before you can navigate. Additionally, Ctrl + k/i to move down/up intellisense menu.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  {
    "key": "capslock",
    "command": "extension.vim_escape",
    "when": "editorTextFocus &amp;amp;&amp;amp; vim.active &amp;amp;&amp;amp; !inDebugRepl"
  },
//allow movement while in insert mode
  {
    "key": "alt+j",
    "command": "cursorLeft",
    "when": "textInputFocus"
  },
  {
    "key": "alt+l",
    "command": "cursorRight",
    "when": "textInputFocus"
  },
  {
    "key": "alt+i",
    "command": "cursorUp",
    "when": "textInputFocus"
  },
  {
    "key": "alt+k",
    "command": "cursorDown",
    "when": "textInputFocus"
  },
//move down/up for intellisense menu
  {
    "key": "ctrl+k",
    "command": "selectNextSuggestion",
    "when": "suggestWidgetMultipleSuggestions &amp;amp;&amp;amp; suggestWidgetVisible &amp;amp;&amp;amp; textInputFocus"
  },
  {
    "key": "ctrl+i",
    "command": "selectPrevSuggestion",
    "when": "suggestWidgetMultipleSuggestions &amp;amp;&amp;amp; suggestWidgetVisible &amp;amp;&amp;amp; textInputFocus"
  },
  {
    "key": "ctrl+k",
    "command": "workbench.action.quickOpenSelectNext",
    "when": "inQuickOpen"
  },
  {
    "key": "ctrl+i",
    "command": "workbench.action.quickOpenSelectPrevious",
    "when": "inQuickOpen"
  },
//move down/up for other list menu
  {
    "key": "k",
    "command": "list.focusDown",
    "when": "listFocus &amp;amp;&amp;amp; !inputFocus"
  },
  {
    "key": "i",
    "command": "list.focusUp",
    "when": "listFocus &amp;amp;&amp;amp; !inputFocus"
  }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;This is my entire keybindings.json file. I recommended you copy/paste the whole file.&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/Apestein/vscode-configs" rel="noopener noreferrer"&gt;Repo&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vim</category>
      <category>vscode</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
