<?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: Phil Tenteromano</title>
    <description>The latest articles on DEV Community by Phil Tenteromano (@ptenteromano).</description>
    <link>https://dev.to/ptenteromano</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%2F181906%2F06290c4a-1cc2-4e30-a520-be4eebc44821.jpg</url>
      <title>DEV Community: Phil Tenteromano</title>
      <link>https://dev.to/ptenteromano</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ptenteromano"/>
    <language>en</language>
    <item>
      <title>Concurrency in Golang with a Binary Search Problem</title>
      <dc:creator>Phil Tenteromano</dc:creator>
      <pubDate>Fri, 24 Jun 2022 18:04:52 +0000</pubDate>
      <link>https://dev.to/vetswhocode/concurrency-in-golang-with-a-binary-search-problem-2j5b</link>
      <guid>https://dev.to/vetswhocode/concurrency-in-golang-with-a-binary-search-problem-2j5b</guid>
      <description>&lt;h2&gt;
  
  
  Problem
&lt;/h2&gt;

&lt;p&gt;Solving problems with Go can be a really fun and rewarding experience. In this post, I'll go through a "medium" Leetcode challenge "&lt;a href="https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/" rel="noopener noreferrer"&gt;Find First and Last Position of Element in Sorted Array&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;The problem is fairly straight forward - it's a sorted array, so we know we can use Binary Search. However, the array is non-decreasing, meaning that elements are allowed to repeat. We're given the task to return a size-2 array with the start and ending index of where the targeted element exists in the array. &lt;/p&gt;

&lt;p&gt;Here is the prompt: &lt;br&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%2Fciex87mmnaky273d4bmk.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%2Fciex87mmnaky273d4bmk.png" alt="Leetcode prompt for Find First and Last Position of Element in Sorted Array" width="735" height="383"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Solution Steps
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Try to think of a mental solution for yourself before reading any further.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ignoring the trivial linear solution, we'll focus on the Binary Search solution. Let's think of the steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Binary Search for the &lt;code&gt;target&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Split the array into "lower" and "upper"&lt;/li&gt;
&lt;li&gt;Binary Search on both, separately&lt;/li&gt;
&lt;li&gt;Repeat until both splits no longer find the target&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Pretty straight forward, I had a lot of fun solving it with Go - most of the syntax is similar to other languages. One of Go's most important features is how simple it makes Concurrency and multi-threading. It uses a data type called &lt;a href="https://gobyexample.com/channels" rel="noopener noreferrer"&gt;Channels&lt;/a&gt; with its native &lt;a href="https://gobyexample.com/goroutines" rel="noopener noreferrer"&gt;Goroutine&lt;/a&gt; to synchronize data across threads. Think of it as &lt;code&gt;async / await&lt;/code&gt; in other languages.&lt;/p&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;We'll make a simple Binary Search method, with runtime of &lt;code&gt;O(log n)&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// BinarySearch method&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;mid&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&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;return&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We'll call this method a few times, but on ever-decreasing slices of the array - we'll never call it with the same memory space twice.&lt;/p&gt;

&lt;p&gt;Now we can easily find any initial target:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;searchRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Initial Search&lt;/span&gt;
    &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Didn't find it, return early&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c"&gt;// TODO: finish function&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we have the early return, when the &lt;code&gt;target&lt;/code&gt; does not exist at all. But now what happens when we find it? Well we need to search up and down the array. We can of course do this linearly, but think about the worst case: what if theres an array of 10 million elements, all &lt;code&gt;target&lt;/code&gt;. If we started with the center - now we have to linearly crawl through 5 million elements up and down the array. Not great!&lt;/p&gt;

&lt;p&gt;Because of that, we'll stick with Binary Search. Golang allows us to cut up its &lt;code&gt;slice&lt;/code&gt; datatype (slices are pretty much arrays, with a lot more flexibility, read more &lt;a href="https://gobyexample.com/slices" rel="noopener noreferrer"&gt;here&lt;/a&gt;). Without using concurrency, here's the rest of the method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;searchRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="c"&gt;// ...&lt;/span&gt;

&lt;span class="c"&gt;// Found target, lets search left and right&lt;/span&gt;
    &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt;

    &lt;span class="c"&gt;// Search lower half of array&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Search upper half of array&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;        
        &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// temp is reindexed at 0 - account for that&lt;/span&gt;
        &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;high&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;Pretty straight forward, we're just binary searching until we no longer find the element on each slice. Great! This passes on Leetcode, and we can be done. But how can we make this a little better? A primary bottleneck with this code is the fact that the "Upper" search is completely blocked until the "Lower" search completes. &lt;/p&gt;

&lt;p&gt;We have an opportunity here - the two for loops are acting on completely separate memory addresses. Let's see what we can do with &lt;code&gt;Goroutines&lt;/code&gt; and a &lt;code&gt;Channel&lt;/code&gt;, here's the entire completed function, with added concurrency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;searchRange&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Initial Search&lt;/span&gt;
    &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Didn't find it, return early&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Hold our data from the threads&lt;/span&gt;
    &lt;span class="n"&gt;bounds&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;chan&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Search lower half of array, in its own thread (goroutine)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;low&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; 
        &lt;span class="c"&gt;// Shovel the lower-bound into the Channel&lt;/span&gt;
        &lt;span class="n"&gt;bounds&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;low&lt;/span&gt;
    &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Search upper half of array, in its own thread (goroutine)&lt;/span&gt;
    &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;findTarget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;break&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;high&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;temp&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="c"&gt;// Shovel the upper-bound into the Channel&lt;/span&gt;
        &lt;span class="n"&gt;bounds&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;
    &lt;span class="p"&gt;}(&lt;/span&gt;&lt;span class="n"&gt;high&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;newLow&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt;
    &lt;span class="n"&gt;newHigh&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt;

    &lt;span class="c"&gt;// No garauntee which one finishes first, so order them&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;newLow&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;newHigh&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;newLow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newHigh&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;newHigh&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newLow&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="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;newLow&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;newHigh&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;Now, we create an anonymous function and call it immediately, but we use the &lt;code&gt;go&lt;/code&gt; keyword to run a Goroutine. With the scope of the &lt;code&gt;bounds&lt;/code&gt; Channel, we can shovel data in and out of it. When pulling data out of the Channel (&lt;code&gt;&amp;lt;-bounds&lt;/code&gt;), Go will block until there is actually data there.&lt;/p&gt;

&lt;p&gt;This means that both the "lower" and "upper" slices will be processed simultaneously! Congratulations, you just solved a Leetcode challenge using thread-safe concurrency💪🧵!&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow up
&lt;/h2&gt;

&lt;p&gt;We can also clean this code up a bit by pulling the functions for "lower" and "upper" out into their own methods. This would make the primary &lt;code&gt;searchRange&lt;/code&gt; method a bit cleaner. But for the sake of simplicity, I left them in.&lt;/p&gt;

</description>
      <category>go</category>
      <category>algorithms</category>
      <category>concurrency</category>
      <category>leetcode</category>
    </item>
    <item>
      <title>Infinite Scroll with Remix Run</title>
      <dc:creator>Phil Tenteromano</dc:creator>
      <pubDate>Wed, 16 Feb 2022 15:01:44 +0000</pubDate>
      <link>https://dev.to/vetswhocode/infinite-scroll-with-remix-run-1g7</link>
      <guid>https://dev.to/vetswhocode/infinite-scroll-with-remix-run-1g7</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://remix.run/docs/en/v1" rel="noopener noreferrer"&gt;Remix Run&lt;/a&gt; has landed and has created a lot of buzz in the the javascript framework world. After digging in, it motivated me to try it out by starting a web project that I've put to the side for far too long. One of the main features of this project is viewing a list of an arbitrary amount of photos, fed from a Rails API. This means infinite scroll. A video of the final result is at the bottom.&lt;/p&gt;

&lt;p&gt;Traditionally, with client side react, we'd just listen to some breakpoint on scroll or use a virtualization tool package like react-virtual. Then we fire off our own methods, merge the state, and repeat.&lt;/p&gt;

&lt;p&gt;Remix Run however, handles its components both on the server (SSR) and in the browser. When I was first trying out infinite scroll, I found that I was fighting against the &lt;code&gt;loader&lt;/code&gt; and &lt;code&gt;action&lt;/code&gt; conventions. It felt wrong, and I knew there had to be a better way. Only once I better understood that Remix's url routes are &lt;em&gt;also it's api routes&lt;/em&gt;, I began to piece it together.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reader note&lt;/strong&gt;: This infinite scroll is built without any other dependencies (the scroll-breakpoint method). The styling is done with &lt;code&gt;tailwindcss&lt;/code&gt;, which I think pairs really well with Remix. The Rails API always returns a &lt;code&gt;json&lt;/code&gt; response. In this case the &lt;code&gt;fetchPhotos&lt;/code&gt; method returns a response in the format:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;photos: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;url: &lt;/span&gt;&lt;span class="s2"&gt;"some_url"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;pid: &lt;/span&gt;&lt;span class="s2"&gt;"12345"&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="p"&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;The &lt;code&gt;fetchPhotos&lt;/code&gt; abstraction can be replaced with any API or database call for data of your choosing.&lt;/p&gt;

&lt;p&gt;We'll solve this problem in three steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a client-side listener for scroll events&lt;/li&gt;
&lt;li&gt;Establish a determined breakpoint for when the scroll should fire a data fetch&lt;/li&gt;
&lt;li&gt;Merge the newly fetched data into the current data. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;All while allowing this process to repeat until there is no more data to be fetched. Let's start!&lt;/p&gt;

&lt;h2&gt;
  
  
  Leveraging The Scroll
&lt;/h2&gt;

&lt;p&gt;I created a component at &lt;code&gt;app/routes/photos/_index.tsx&lt;/code&gt;. In Remix, this is accessible in the browser at &lt;code&gt;/photos&lt;/code&gt;. The Rails API I'm using uses a &lt;code&gt;page&lt;/code&gt; param to get photos in increments of 10. The initial code to load the page looks like this:&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;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LoaderFunction&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;remix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fetchPhotos&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;~/utils/api/restful&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PhotoHash&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;~/utils/api/types&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoaderFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&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="c1"&gt;// Pass a page number to the Rails API&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPhotos&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&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="nf"&gt;Photos&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;photos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotoHash&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;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;container mx-auto space-y-2 md:space-y-0 md:gap-2 md:grid md:grid-cols-2 py-4&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;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;photo&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;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;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;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&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;w-full border-green-200 h-52&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;img&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;mx-auto object-center object-cover h-52 rounded hover:shadow-2xl&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
              &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
              &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`photo-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;photo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;pid&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="sr"&gt;/&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;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;p&gt;But this only gets the first page of photos! &lt;code&gt;fetchPhotos(1)&lt;/code&gt; is just a call to the Rails server with a first page argument. When the page loads, the &lt;code&gt;loader&lt;/code&gt; will fetch the photos and render them into the jsx. The problem remains, how do we dynamically fetch more photos during scroll. Keep in mind that Remix also &lt;em&gt;runs this code on the server&lt;/em&gt; where there is no &lt;code&gt;window&lt;/code&gt; or &lt;code&gt;document&lt;/code&gt;, etc. So we need to rethink our approach!&lt;/p&gt;

&lt;p&gt;What we need now is a &lt;strong&gt;client side&lt;/strong&gt; listener for scroll events and the browser height. We'll need some React for that:&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&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="c1"&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;Photos&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;photos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotoHash&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;scrollPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setScrollPosition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setClientHeight&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="c1"&gt;// Add Listeners to scroll and client resize&lt;/span&gt;
  &lt;span class="nf"&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;scrollListener&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setClientHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHeight&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setScrollPosition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;scrollY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="c1"&gt;// Avoid running during SSR&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scrollListener&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Clean up&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nb"&gt;window&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;scroll&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scrollListener&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&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;Awesome, now if you add a &lt;code&gt;console.log&lt;/code&gt; inside the &lt;code&gt;scrollListener&lt;/code&gt; you'll see it fire &lt;em&gt;very&lt;/em&gt; frequently whenever you scroll, which is a great start. We also check for the &lt;code&gt;window&lt;/code&gt;, ensuring the callback only gets attached and removed when the component is rendered on the client. Now we can track where we are during scrolling.&lt;/p&gt;

&lt;p&gt;The next step now is to figure out when we want to fire our call to fetch more photos. To do that, we also need to find the height of the parent &lt;code&gt;div&lt;/code&gt; that contains all the photos. We'll need a &lt;code&gt;useCallback&lt;/code&gt; listener to attach to that parent:&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;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useCallback&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="c1"&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;Photos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
  &lt;span class="c1"&gt;// We won't care about height until a client-side render&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;height&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&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="c1"&gt;// Set height of the parent container whenever photos are loaded&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;divHeight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&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;node&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setHeight&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getBoundingClientRect&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;height&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;photos&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&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;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;divHeight&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="c1"&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;p&gt;Attaching this method as the &lt;code&gt;ref&lt;/code&gt; of the parent &lt;code&gt;div&lt;/code&gt; allows us to set the height into our components state. Furthermore, when we create a dependency on &lt;code&gt;photos.length&lt;/code&gt; we are ensuring the container's &lt;code&gt;height&lt;/code&gt; is set properly every time the number of photos change, which would alter the height of that container div.&lt;/p&gt;

&lt;p&gt;Now we just need to know when we are firing our API call. We can do a little custom algebra here. &lt;strong&gt;Note: This all varies based upon your layout, the media size (mobile, large desktops, etc). YMMV! At the very least, the parent div should be scrollable from the initial load for this to work properly.&lt;/strong&gt;&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="c1"&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="nc"&gt;Photos&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;shouldFetch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShouldFetch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;

  &lt;span class="c1"&gt;// Listen on scrolls. Fire on some self-described breakpoint&lt;/span&gt;
  &lt;span class="nf"&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;shouldFetch&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;height&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;scrollPosition&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;height&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&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="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;SHOULD BE FETCHING!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;setShouldFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;clientHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scrollPosition&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This check &lt;code&gt;clientHeight + scrollPosition + 100 &amp;lt; height&lt;/code&gt; is the scroll check, and is completely customizable in your own infinite scroll. This fires with the &lt;code&gt;clientHeight&lt;/code&gt; and &lt;code&gt;scrollPosition&lt;/code&gt; dependencies so once the criteria is met, we get through the Guard clauses and reach that &lt;code&gt;console.log&lt;/code&gt; statement. Update: as of a newer version of remix, I've added the next condition &lt;code&gt;fetcher.state == "loading"&lt;/code&gt;. We need this to ensure we only refetch when the fetcher is not already fetching! Try it yourself, the log should fire once and only once - preventing further calls due to &lt;code&gt;setShouldFetch(false)&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Remix Conventions
&lt;/h2&gt;

&lt;p&gt;So now we want to replace that &lt;code&gt;console.log&lt;/code&gt; with a real API call and merge them into our photos; allowing this to repeat for as long as there are pages with photo data. But the question with Remix is – where should we call our API fetch from?&lt;/p&gt;

&lt;p&gt;Remix's routes &lt;em&gt;are also its API routes&lt;/em&gt;. This means that if you want to fetch data, well, you should hit your own routes. In this case the route is itself (&lt;code&gt;/photos&lt;/code&gt;), just with a different &lt;code&gt;page&lt;/code&gt; parameter (to be sent to our Rails API). Let's look at the &lt;code&gt;loader&lt;/code&gt; for a second, and add some url query parameter for the page:&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="c1"&gt;//...&lt;/span&gt;
&lt;span class="c1"&gt;// Pull page down from the loader's api request&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;URLSearchParams&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;page&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loader&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LoaderFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;request&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;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getPage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;searchParams&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;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchPhotos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&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;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;photos&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="nf"&gt;Photos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By parsing the &lt;code&gt;page&lt;/code&gt; URL parameter, we can now make this &lt;code&gt;loader&lt;/code&gt; a little bit more dynamic. Hopefully you see where I'm going with this – to fetch more data, we just continuously have to &lt;em&gt;load&lt;/em&gt; our data from this route, just with another parameter.&lt;/p&gt;

&lt;p&gt;How does Remix do this? There's a nice little hook called &lt;code&gt;useFetcher&lt;/code&gt; – you can see the documentation on it &lt;a href="https://remix.run/docs/en/v1/api/remix#usefetcher" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Most of the time, &lt;code&gt;loader&lt;/code&gt; and &lt;code&gt;action&lt;/code&gt; are all you need, but &lt;code&gt;useFetcher&lt;/code&gt; gives us some fantastic flexibility. Specifically, we're gonna leverage our already built &lt;code&gt;loader&lt;/code&gt;, combined with fetcher's &lt;a href="https://remix.run/docs/en/v1/api/remix#fetcherload" rel="noopener noreferrer"&gt;load method&lt;/a&gt;. Let's call it when we hit our scrolling criteria:&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;useLoaderData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;LoaderFunction&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useFetcher&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;remix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&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;Photos&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Start with two because 1 was pre-loaded&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;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPage&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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;fetcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFetcher&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;

  &lt;span class="c1"&gt;// Listen on scrolls. Fire on some self-described breakpoint&lt;/span&gt;
  &lt;span class="nf"&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;shouldFetch&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;height&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clientHeight&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;scrollPosition&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;height&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;loading&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="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/photos?index&amp;amp;page=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nf"&gt;setShouldFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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;clientHeight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scrollPosition&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alright, we are leveraging the fetcher to load the next page (2) when we reach close to the bottom of the parent div. The &lt;code&gt;fetcher&lt;/code&gt; calls the &lt;code&gt;loader&lt;/code&gt; from our route, and applies a &lt;code&gt;page&lt;/code&gt; query parameter. Keep in mind, we add the &lt;code&gt;index&lt;/code&gt; parameter because this route is an index route; refer to the &lt;code&gt;useFetcher&lt;/code&gt; docs for greater detail. So now we need to pull the newly fetched photos out and add them to the UI. And what about &lt;em&gt;continuously&lt;/em&gt; grabbing more data like "Infinite Scroll" promises? Well, the &lt;code&gt;fetcher&lt;/code&gt; is stateful, so we'll leverage this in a new, final &lt;code&gt;useEffect&lt;/code&gt;:&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="c1"&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;Photos&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;initialPhotos&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useLoaderData&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PhotoHash&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;photos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setPhotos&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPhotos&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;//...&lt;/span&gt;

  &lt;span class="c1"&gt;// Merge photos, increment page, and allow fetching again&lt;/span&gt;
  &lt;span class="nf"&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="c1"&gt;// Discontinue API calls if the last page has been reached&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;fetcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;fetcher&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;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setShouldFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&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="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Photos contain data, merge them and allow the possiblity of another fetch&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;fetcher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;fetcher&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;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setPhotos&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;prevPhotos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;PhotoHash&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;prevPhotos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;fetcher&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="nf"&gt;setPage&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;number&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;page&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setShouldFetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&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;fetcher&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="c1"&gt;//...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can read about &lt;code&gt;fetcher.data&lt;/code&gt; &lt;a href="https://remix.run/docs/en/v1/api/remix#fetcherdata" rel="noopener noreferrer"&gt;here&lt;/a&gt;; it's pretty much just the result of &lt;code&gt;.load()&lt;/code&gt;, which in our case is an array of photos. In this &lt;code&gt;useEffect&lt;/code&gt;, we depend on &lt;code&gt;fetcher.data&lt;/code&gt;, and call this whenever that has changed - which directly corresponds to the previous &lt;code&gt;useEffect&lt;/code&gt; where &lt;code&gt;fetcher.load(...)&lt;/code&gt; is called.&lt;/p&gt;

&lt;p&gt;Let's dive in to this new &lt;code&gt;useEffect&lt;/code&gt;. When the photos array is 0 we stop fetching all together, meaning we've reached the end of all possible photos (your data source might be different). This prevents the API from being spammed, or making unnecessary calls. &lt;/p&gt;

&lt;p&gt;But when there is photo data in the array, we merge those newly fetched photos with our current photos. Then we increment the page number by one, and finally we set our &lt;code&gt;shouldFetch&lt;/code&gt; to true, signaling that we want to get the next page when the user has scrolled enough.&lt;/p&gt;

&lt;p&gt;Behind the scenes, once the new photos are merged, the container &lt;code&gt;div&lt;/code&gt; will grow. This causes a re-size of the &lt;code&gt;height&lt;/code&gt; variable. When a user scrolls, the &lt;code&gt;useEffect&lt;/code&gt; with &lt;code&gt;fetcher.load()&lt;/code&gt; will continue to be triggered but the breakpoint has now changed, forcing the Guard clause to return early. &lt;em&gt;Only when the user scrolls&lt;/em&gt; and hits that newly calculated breakpoint will the Guard clauses be bypassed, and &lt;code&gt;fetcher.load()&lt;/code&gt; will be called again with the next page number. This will eventually update &lt;code&gt;fetcher.data&lt;/code&gt;, causing another photo merge. This process will repeat as the user scrolls, until there is no more data being received from the API.&lt;/p&gt;

&lt;p&gt;Below is a little preview of how it works in my browser, along with my console output. You can also view the code for the whole file at this &lt;a href="https://gist.github.com/ptenteromano/e42fe33622a26ba3fdd49b51109203c7" rel="noopener noreferrer"&gt;gist&lt;/a&gt;.&lt;/p&gt;

&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%2Fk4jc3ydfmoqth4y9w9np.gif" 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%2Fk4jc3ydfmoqth4y9w9np.gif" alt="Browser infinite scroll, loading on scroll" width="200" height="103"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you all for reading! I hope this helps you deliver a dependency free, Remix-like infinite scroll experience. Let me know if you have any feedback or suggestions in the comments below. Good luck and have fun with Remix!&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>How does a baby pronounce Memorization? Memoization!</title>
      <dc:creator>Phil Tenteromano</dc:creator>
      <pubDate>Sat, 21 Nov 2020 01:18:03 +0000</pubDate>
      <link>https://dev.to/vetswhocode/how-does-a-baby-pronounce-memorization-memoization-4e0c</link>
      <guid>https://dev.to/vetswhocode/how-does-a-baby-pronounce-memorization-memoization-4e0c</guid>
      <description>&lt;p&gt;Memoization is a concept of computation in which common results are stored, or cached, to avoid re-calculation. This is extremely useful when an algorithm has an increasing number of similarly computed branches. Let's dive into a common example with Javascript, with the recursive Fibonacci sequence.&lt;/p&gt;

&lt;p&gt;Here's a simple recursive Fib:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&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;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&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;The big O of this algorithm evaluates to &lt;code&gt;O(2^n)&lt;/code&gt;. Hopefully we can all agree - this is abysmal.&lt;/p&gt;

&lt;p&gt;Let's evaluate the line &lt;code&gt;return fib(n - 1) + fib(n - 2);&lt;/code&gt;. At every recursive call, we are now branching down into two more Fib calls; and so on and so on. However, Fib looks backwards at itself: &lt;code&gt;n-1&lt;/code&gt; and &lt;code&gt;n-2&lt;/code&gt;. Which means there will be many recursive Fib's which want to calculate the same thing. If we leave them to their devices, the call stack could easily be overwhelmed, and even for relatively small &lt;code&gt;n&lt;/code&gt;, computation will take a &lt;strong&gt;long&lt;/strong&gt; time (try &lt;code&gt;fib(50)&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This is where memoization comes in. It allows us to avoid every recursive Fib call from branching into clones like something out of the Matrix movies. How? By caching the result when we've already found the answer the first time. That way, when another branch wants to calculate a &lt;code&gt;fib(k)&lt;/code&gt; for some &lt;code&gt;k &amp;gt; 2&lt;/code&gt;, we don't have to keep climbing the call stack with two more subsequent Fibs - we could return early with a concrete result.&lt;/p&gt;

&lt;p&gt;Let's build our memoization function, we'll call it &lt;code&gt;memo&lt;/code&gt;&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;funcToMemo&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;cache&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;

  &lt;span class="c1"&gt;// Return a new function that is memoized&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// We've computed this already!&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;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;args&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;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="c1"&gt;// Never seen it? Compute it, but store it after&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;funcToMemo&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;result&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;result&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Javascript treats functions as &lt;strong&gt;first-class citizens&lt;/strong&gt;, so we can utilize &lt;strong&gt;closures&lt;/strong&gt; that allow us to build this memoization function. I'd suggest reading up on closures and first-class functions if you're unfamiliar.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;memo&lt;/code&gt; function passes a &lt;code&gt;cache&lt;/code&gt; object to an anonymous function which is now able to store, collect, and retain that information through recursive calls.&lt;/p&gt;

&lt;p&gt;Now that we have this closure-enabled memoization function. We can wrap it around our &lt;code&gt;fib&lt;/code&gt; function. However, due to how memory and naming is aligned, we have to sync it with the proper function names. Let's assume we want to call our memoized fib &lt;code&gt;memoFib&lt;/code&gt;. We can do that easily with:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;memoFib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, since the &lt;code&gt;fib&lt;/code&gt; function recursively calls the &lt;code&gt;fib&lt;/code&gt; function itself, it will lose scope on the &lt;code&gt;memoFib&lt;/code&gt;, and won't know about its brand new, speedy self. To really make this work, we have to update the recursive call with the anticipated memoized function name:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;2&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;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Recursively call the fast memoized fib&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;memoFib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;memoFib&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;2&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;memoFib&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fib&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And we're done! With a little proactive coding, we can call some insanely large fib numbers we would otherwise not be able to run at all. Try this with something like &lt;code&gt;memoFib(500)&lt;/code&gt; - the number is massive, and computed fast!&lt;/p&gt;

</description>
      <category>computerscience</category>
      <category>javascript</category>
      <category>functional</category>
      <category>closures</category>
    </item>
    <item>
      <title>Merge into Master Often? Automate!</title>
      <dc:creator>Phil Tenteromano</dc:creator>
      <pubDate>Wed, 04 Mar 2020 18:11:45 +0000</pubDate>
      <link>https://dev.to/vetswhocode/merge-master-often-automate-2fjg</link>
      <guid>https://dev.to/vetswhocode/merge-master-often-automate-2fjg</guid>
      <description>&lt;h1&gt;
  
  
  Working on a Repo
&lt;/h1&gt;

&lt;p&gt;My engineering department is decently sized, about 50-60 engineers all pushing to (typically) the same repository. Changes happen all the time that force us to merge an updated master into a working branch. This is due to a number of different reasons. One being our heavy reliance on tests from a number of different frameworks, across a broad codebase.&lt;/p&gt;

&lt;p&gt;Recently, I found myself constantly running &lt;code&gt;git fetch&lt;/code&gt; and &lt;code&gt;git merge origin/master&lt;/code&gt;. This redundancy irked me. I, like most sane developers, love the terminal and the command line. So I thought back to my school days were we played around with bash and making our own custom commands. So I decided to make things a &lt;em&gt;little&lt;/em&gt; easier.&lt;/p&gt;

&lt;h1&gt;
  
  
  Automation
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;Note: I work on MacOS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This'll be quick! In my &lt;code&gt;~/.bash_profile&lt;/code&gt; I put the following code snippet:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Load custom bash functions
if [ -r ~/.custom_cmds.sh ]; then
  source ~/.custom_cmds.sh
fi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This simply looks for the &lt;code&gt;~/.custom_cmds.sh&lt;/code&gt; file, and loads it into every new bash session (by default from &lt;code&gt;~/.bash_profile&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Create the custom commands file and inside of it, simply put:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;merge_master() {
  git fetch;
  git merge origin/master;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a bash function called &lt;code&gt;merge_master&lt;/code&gt;. Of course, you can name it anything you want, but I went with this.&lt;/p&gt;

&lt;p&gt;Afterwards, I ran &lt;code&gt;chmod u+x ~/.custom_cmds.sh&lt;/code&gt; to ensure execution rights of the file. Now just restart the terminal, or run &lt;code&gt;source ~/.bash_profile&lt;/code&gt; and &lt;strong&gt;Boom&lt;/strong&gt;. You have your first custom command line function! While simple, it makes me a little happier - run it from any of your repositories with a simple &lt;code&gt;merge_master&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;With this bash syntax, we can now create any automated function we want that will simplify our command-line-lives. Just add it into your &lt;code&gt;~/.custom_cmds.sh&lt;/code&gt; file!&lt;/p&gt;

&lt;p&gt;What else do you like to automate? Bash is incredibly powerful - the options are limitless!&lt;/p&gt;

</description>
      <category>bash</category>
      <category>automation</category>
      <category>terminal</category>
      <category>devops</category>
    </item>
    <item>
      <title>The Three P's of Learning How to Code</title>
      <dc:creator>Phil Tenteromano</dc:creator>
      <pubDate>Wed, 09 Oct 2019 11:59:00 +0000</pubDate>
      <link>https://dev.to/ptenteromano/the-three-p-s-of-learning-how-to-code-4f70</link>
      <guid>https://dev.to/ptenteromano/the-three-p-s-of-learning-how-to-code-4f70</guid>
      <description>&lt;p&gt;Recently, I made the decision to seek a TA / tutoring position at my university's CS department. As I am currently in my final semester of graduate school, I only saw the positives of being a tutor:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Help others overcome struggles&lt;/li&gt;
&lt;li&gt;Improve peer-review skills&lt;/li&gt;
&lt;li&gt;Reinforce my own learning&lt;/li&gt;
&lt;li&gt;Give back to academia, especially my alma mater&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So far, tutoring has been an absolute joy (while the grading part is... tedious). As the semester has gone on, more and more students have been coming to me during my tutoring hours. I also frequently tutor by appointment, whenever I have free time during my day.&lt;/p&gt;

&lt;p&gt;Before I continue, I want to be specific about the tutoring topics and what these students are learning. I'm the TA for the CS2200 course - Data Structures. This course is the third programming course in the CS curriculum (after CS1, CS2, and not counting math-courses). The curriculum revolves around C++, a language I have the utmost respect for (mostly out of fear). TA aside, I tutor any CS student who walks in - and it's almost entirely students from those first three classes seeking help; beginners, if you will.&lt;/p&gt;

&lt;p&gt;A language like C++ can be absolutely DAUNTING for beginners, especially once objects come into play. But this post isn't about C++, because any language can be daunting for beginners. &lt;strong&gt;And from everything I have seen from tutoring, this post isn't even about programming languages&lt;/strong&gt;.&lt;/p&gt;




&lt;center&gt;&lt;h2&gt;Easing Frustrations&lt;/h2&gt;&lt;/center&gt;

&lt;p&gt;Students that come in for tutoring sessions are typically (and predictably) coming in for help on their assignments. The assignments are written out as a page or two of specifications and requirements. Some come in asking specific questions in reference to a bug, while others just give off that 'completely lost' vibe. And since C++ is a compiled language, it can be easy to go from a working program, to throwing your laptop out the window in a few short lines of code.&lt;/p&gt;

&lt;p&gt;The first question I always ask them is: "Does your program compile?"&lt;br&gt;
Their answer is typically: "No", or the "Well it did yesterday, but then..."&lt;/p&gt;

&lt;p&gt;This leads me to the first &lt;strong&gt;"P"&lt;/strong&gt; of Learning How to Code:&lt;/p&gt;

&lt;center&gt;&lt;h1&gt;Piece by Piece&lt;/h1&gt;&lt;/center&gt;

&lt;p&gt;Bonus points for using alliteration?&lt;br&gt;
Almost always I see students trying to read through the entire assignment and tackle it as if it is one big monotonous block. They code and they code one line after the other thinking they are painting a masterpiece. As the saying goes: "to err is human", and that is never more true than when you start coding.&lt;/p&gt;

&lt;p&gt;I challenge them to change their perspective: that they shouldn't look at their code or their program as a Picasso masterpiece. Instead, they should look at it as a jigsaw puzzle. I couldn't tell you where to start on creating a Picasso painting, but I know damn well how to put together a jigsaw puzzle.&lt;/p&gt;

&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%2Fqxewblfxj7yg6phwt6yu.jpg" 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%2Fqxewblfxj7yg6phwt6yu.jpg" alt="Jigsaw Puzzle" width="640" height="426"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I like this analogy because it helps them take a step back and see that all code really is, is just a series of instructions. If you modularize a large instruction set into smaller and smaller subsets you eventually get a bunch of manageable pieces, just like a jigsaw puzzle.&lt;/p&gt;

&lt;p&gt;So I ask them to do multiple reads of an assignment's specifications. Then, when they have a good grasp of what is necessary, start breaking down the whole and implementing a little at a time. Writing a few lines of code, verifying it's validity, and repeating the process is a surefire way to increase efficiency and save you all that frustration when it comes time to fix those errors!&lt;/p&gt;

&lt;p&gt;For new students in my tutoring, I like to go with a Bank Account example. I ask, how could you break the concept of a Bank Account down into manageable chunks? What could you implement and test, one at a time?&lt;/p&gt;

&lt;center&gt;&lt;h1&gt;Pen and Paper&lt;/h1&gt;&lt;/center&gt;

&lt;p&gt;Alliteration again!?&lt;br&gt;
Piggybacking off the first concept, 'Pen and Paper' is exactly what it sounds like. Writing down notes, drawing diagrams, visualizing instruction sets, and all manner of blueprinting are incredibly useful for clearing up the mind. Doing this not only adds to, and increases workflow, but it allows the programmer to take a step back and conceptualize their thoughts.&lt;/p&gt;

&lt;p&gt;Personally, this one took me a while to figure out myself. Now as a tutor, it took me all of 2 days for me to start harping on students to get a pen and paper out. I noticed that when they would come in, they would only have their laptops and stare at them; they'd be banging their heads against a wall trying to code themselves out of their problems. I say, "What're you doing? Do you have a plan? No? Then why not draw one up instead of coding in circles?".&lt;/p&gt;

&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%2Fs2wawrwi7lnwqbt03rdg.jpg" 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%2Fs2wawrwi7lnwqbt03rdg.jpg" alt="Alt Text" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Similarly, I don't tutor by showing them my code, I get on a whiteboard and literally draw diagrams and pseudo code for them. I draw out what's needed and box out what can be separated out as a puzzle piece. I even convey to them that coding is barely even about coding - it's about problem solving. Solve the problem first, then code your solution. And... &lt;strong&gt;boom&lt;/strong&gt;, transition!&lt;/p&gt;

&lt;center&gt;&lt;h1&gt;Problem Solving&lt;/h1&gt;&lt;/center&gt;

&lt;p&gt;I'll take 2/3 on the alliteration.&lt;/p&gt;

&lt;p&gt;Question: "What's a programmers best friend?"&lt;br&gt;
Answer 1: "Google!"&lt;br&gt;
Answer 2: "Stack Overflow!"&lt;/p&gt;

&lt;p&gt;We all solve problems everyday, be it life problems or code problems. I remember when I saw my first C++ compile-time error. It was like reading hieroglyphics, I had absolutely no idea how to interpret it. This was a real challenge for me to overcome, a problem I had to solve!&lt;/p&gt;

&lt;p&gt;Leveraging the first two &lt;strong&gt;P&lt;/strong&gt;'s, Problem Solving seeks to close any loopholes that may come about. With the assumption that the programmer has broken down a large task into manageable smaller ones, and they have properly conceptualize how to implement a small task, then any further problems should now be in their own independent, manageable state. This is where programmer knowledge, or of course the beautiful internet come into play; time to solve that problem.&lt;/p&gt;

&lt;p&gt;If the first two &lt;strong&gt;P&lt;/strong&gt;'s are not followed, then Problem Solving can become a chaotic mess; a place where one error follows another, which follows another, and another, and then you spill coffee on your laptop, etc. Only by breaking things down and understanding can this force future obstacles to become less obscure, with exponentially less influence.&lt;/p&gt;

&lt;p&gt;The cliche, 'nobody knows everything', couldn't be more true than in tech. The internet &lt;em&gt;is&lt;/em&gt; the information age that we live in. It's out there, use it! Of course, if you copy and paste code you don't understand then you're only doing yourself a disservice - this will come back to haunt you!&lt;/p&gt;




&lt;center&gt;Bonus **P**!&lt;/center&gt;

&lt;center&gt;&lt;h2&gt;Practice!&lt;/h2&gt;&lt;/center&gt;

&lt;p&gt;Coding is hard by default, it's rewiring our brains into a new way of thinking. Lectures and videos are great, but they just won't teach you the way real practice would. We learn better and retain more information when we struggle. I am a big believer in exposure, exposure, exposure. Difficult concepts aren't meant to be mastered in a 3 month semester - it takes time, practice, and a dedication to drive on.&lt;/p&gt;

&lt;p&gt;Whether you come from a CS degree, bootcamp, or self-taught background, this bonus &lt;strong&gt;P&lt;/strong&gt; may just be the most important one!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>javascript</category>
      <category>computerscience</category>
      <category>cpp</category>
    </item>
    <item>
      <title>Vets Who Code — Servicing Tech Opportunities to Those Who Served</title>
      <dc:creator>Phil Tenteromano</dc:creator>
      <pubDate>Wed, 03 Jul 2019 18:01:25 +0000</pubDate>
      <link>https://dev.to/vetswhocode/vets-who-code-servicing-tech-opportunities-to-those-who-served-11lc</link>
      <guid>https://dev.to/vetswhocode/vets-who-code-servicing-tech-opportunities-to-those-who-served-11lc</guid>
      <description>&lt;p&gt;When I was separating from the US Army in 2016, I thought I had my future all figured out. I was ready to take on new challenges — I had been accepted to my dream school in NYC, I was going to be surrounded by an incredible family support system, and I had my sights aimed at the tech industry.&lt;/p&gt;

&lt;p&gt;I was lucky enough to have a pretty decent transition; 10 days after my separation date I was in the classroom, solving discrete mathematics problems. “I’m a veteran, I’m adapting to the classroom well, and I’m going into a lucrative industry — I’m set!”, I would say to myself.&lt;/p&gt;

&lt;p&gt;I was naive enough to think that showing up to class and doing well in academia was going to be a golden ticket in the competitive private sector. Unfortunately, that’s not how it was. It hit me like a ton of bricks when I first went out applying for internships; I started off the search process thinking employers would hear me say “I know C++”, and they would be throwing offers at me.&lt;/p&gt;

&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%2F0fmaeyx1mfnbmjvg9g61.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%2F0fmaeyx1mfnbmjvg9g61.png" alt="Sums up my initial job search" width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Boy, was I wrong. I got a ton of advice from an alumni network, my mentor, and my colleagues who had gone through the tech-ringer before — do projects, do practical work, do something outside of the classroom that shows off your skills. It all started to click, and a fire burned inside of me to get after it and do more.&lt;/p&gt;




&lt;h3&gt;Learning as a Lifestyle&lt;/h3&gt;

&lt;p&gt;College was great, but it was a lot of theory. There were projects sure, but not enough — or at least, not individualized to where I can really show it off and impress employers. So I first started going out and learning on Udemy, practicing algorithms on hackerrank, and just doing more in my free time.&lt;/p&gt;

&lt;p&gt;It was fine at first, but after a while I felt a little lost. It was unstructured, clunky, and just overall inefficient. I had a few veteran friends at school and we discussed how being a veteran could help us in the real world. One of the things we really noticed was a lack of veteran communities in our respective fields — it felt lonely. It especially felt lonely after spending years as a soldier surrounded by other soldiers near 24/7. This gave me an idea to start looking for veteran-tech groups that could satisfy that need for camaraderie — except now as soldiers and developers.&lt;/p&gt;




&lt;h3&gt;Finding Vets Who Code&lt;/h3&gt;

&lt;p&gt;I came across Vets Who Code in Summer of 2018 after some online digging and I really was intrigued. Firstly, they had a vetting process (no pun intended); they wanted some proof of basic knowledge in the field, a “prework” exercise that displayed not only skill level, but also a willingness to commit.&lt;/p&gt;

&lt;p&gt;Now, Vets Who Code, or VWC, wasn’t just vetting people to be a part of some exclusive chat-group or something like that. They were providing &lt;b&gt;free training&lt;/b&gt; to those veterans who went out and did the prework, thus showing their drive and their commitment. This training would last about 16–18 weeks, would meet via Slack or video calls 3–4 nights a week, and teach some of the most popular frameworks and technologies being used in the industry.&lt;/p&gt;

&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%2Furphfzrshnu9x6iptmz3.jpeg" 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%2Furphfzrshnu9x6iptmz3.jpeg" width="500" height="277"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was sold. I reached out and let them know my background and why I wanted to be there. Jerome Hardaway got back to me and asked me to provide that golden ticket (the prework). I had created a website earlier in the year, but it was a github Pull Request on their repository that really caught their eye. It was a gratifying experience just to be accepted and engage in a new chapter of learning. It was really exciting to be with other veterans, in a community focused on the tech industry.&lt;/p&gt;

&lt;p&gt;My training cohort ran for 17 weeks during the Fall of 2018, while I also maintained a full-time school schedule. The VWC cohort really set the tone by giving us hands on practice and guidance to understand frameworks like React and Express, while exposing us to real-world industry experience. This again, all coming from fellow veterans. I just wasn’t getting that kind of utility out of school (academia can be real bubble).&lt;/p&gt;

&lt;p&gt;So on top of the theory I was getting in the classroom, I was taking online classes with VWC and learning about all the nuanced topics of the industry. We were coding non-stop; our instructor, Brad Hankee, did an incredible job of keeping myself and the other veterans in the cohort engaged and challenged all at the same time. Even with my CS background, the cohort was able to be individualized enough to give each veteran a chance at breaking the mold and feeling confident about entering the tech space.&lt;/p&gt;




&lt;h3&gt;Hard Work → Reward&lt;/h3&gt;

&lt;p&gt;VWC’s cohort focused a lot on the Javascript language, and rightfully so, as it is pretty much the most widely used language in the industry. That right there did so much for me — I had barely even wrote a line of javascript before that (and as a CS major!?).&lt;/p&gt;

&lt;p&gt;Before VWC, I had struggled so hard to find an internship. The Summer before I started the cohort, I had settled on an internship with a just-seeded start up with almost no money to spare, and more importantly, no mentorship. It wasn’t a great experience.&lt;/p&gt;

&lt;p&gt;I finished the VWC cohort in December of 2018 and I knew it was about time to start applying for internships.&lt;/p&gt;

&lt;p&gt;&lt;b&gt;Let me say this: &lt;/b&gt; I had &lt;b&gt;two offers&lt;/b&gt; by January from prestigious companies.&lt;/p&gt;

&lt;p&gt;I was ecstatic to hear that good news. To put this in perspective, those offers came after I applied to maybe 5% of my total applications the year before. If that doesn’t speak volumes about what VWC does, I don’t know what does.&lt;/p&gt;

&lt;p&gt;But wait — theres more! VWC doesn’t just offer this free training and send you on your way. It’s a community of veterans; after my cohort ended I felt empowered and only wanted more of something like this. I am 100% an active member of the community and communicate daily in the slack channel.&lt;/p&gt;

&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%2Fgh4trkeia4t6zbjsubk5.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%2Fgh4trkeia4t6zbjsubk5.png" width="800" height="454"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After my offers, Jerome asked me to contribute to teaching in the next cohort. I was given 2 weeks of teaching an expanded ‘Computer Science’ curriculum that wasn’t fleshed out as much in previous cohorts. Excited and honored, I said yes — I considered it a great way to give back to my fellow veterans, and to VWC.&lt;/p&gt;

&lt;p&gt;Overall, Vets Who Code was an absolute catalyst to get me out of a slump and propel me to greater heights. It doesn’t matter the extent of technological background either, every single veteran is welcome. &lt;b&gt;We only ask one thing — drive and commitment&lt;/b&gt;. Learning to code is a challenging road, but veterans are used to challenging roads. Whether you’re a veteran who has never written a line of code or you’ve been working at Google, we would love to have you on board and help you reach your potential.&lt;/p&gt;

</description>
      <category>veterans</category>
      <category>career</category>
      <category>javascript</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
