<?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: Mohamed Sharif</title>
    <description>The latest articles on DEV Community by Mohamed Sharif (@msharifhub).</description>
    <link>https://dev.to/msharifhub</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1351517%2F16787b59-fc8f-42ad-955b-d442c91f27ad.jpeg</url>
      <title>DEV Community: Mohamed Sharif</title>
      <link>https://dev.to/msharifhub</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/msharifhub"/>
    <language>en</language>
    <item>
      <title>Implementing A Dynamic Grid With With Slicing</title>
      <dc:creator>Mohamed Sharif</dc:creator>
      <pubDate>Mon, 21 Jul 2025 07:30:05 +0000</pubDate>
      <link>https://dev.to/msharifhub/implementing-a-dynamic-grid-with-with-slicing-4f3j</link>
      <guid>https://dev.to/msharifhub/implementing-a-dynamic-grid-with-with-slicing-4f3j</guid>
      <description>&lt;p&gt;Here we have a problem: How to implement a  grid that displays a single row and the number of  columns should be based on a predetermined number that corresponds to the dynamic change of the winner width. Or a more better explanation is that the items being rendered should fit within the  html node  and displayed as single row but number of items to be rendered should be based on the size of the width. Each single item should have the same width and height and it should have a 16/9 (video caption).&lt;/p&gt;

&lt;p&gt;I will explain this functionality giving an example  of an interface  you might encounter either using Netflix or youtube. So, we want have 1 row where we display this history of videos the user watched.  The display should be only 1 row. Below is a screen shot of what we want to implement&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%2Fzqtwvd3suvnpmtzn5lz8.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%2Fzqtwvd3suvnpmtzn5lz8.png" alt=" " width="800" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What happens if we do not control the number of items to be displayed ?&lt;/p&gt;

&lt;p&gt;So lets try out:&lt;/p&gt;

&lt;p&gt;In this example, I will be using React-TypeScript and TailwindCSS. Supposedly we grab our array of items and we map the array on a div. If we set as a flex row, depending on how many items you have, it will shrink so all items can fit.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    &amp;lt;div className="flex flex-row"&amp;gt;
          {loading &amp;amp;&amp;amp; &amp;lt;SpinningCircle /&amp;gt;}
          {videosWatched.length &amp;gt; 0 &amp;amp;&amp;amp;
            !loading &amp;amp;&amp;amp;
            !error &amp;amp;&amp;amp;
            videosWatched.map((video) =&amp;gt; (
              &amp;lt;div key={`${video.id}-${video.__typename}`} className="flex flex-col w-full  gap-4 rounded overflow-hidden"&amp;gt;
                &amp;lt;div className="aspect-video"&amp;gt;
                  &amp;lt;img alt="" src={video.thumbnailDefault ?? ''} className=" h-full w-full object-cover " /&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div&amp;gt; {sliceText({ s: video.title })}&amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            ))}
        &amp;lt;/div&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

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

&lt;p&gt;we can not set a height or width for the div that controls  height and width of the thumbnails because if we do so then elements will collapse. Using the aspect video class it will increase the width  as the window.innerWidth gets larger. the problem is we rendering all  and when the inner.width for example is below &amp;lt; 480px and we have many items, it will shrink. we could simply set a height and width and would null out the aspect video and use the  overflow-x-scroll class provided by TailwindCss.  That way we would have a fixed size and user could scroll. But thats not what we want.  The UI should maintain an aspect video and when the window.innerWidth  gets smaller we want to display a certain number of videos so we still maintain a predetermined size handled by the aspect video class. If we slice the array to only 2 items when the inner width is for example less than 480 pixel we can get an idea of each item being rendered&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 &amp;lt;div className="flex flex-row"&amp;gt;
          {loading &amp;amp;&amp;amp; &amp;lt;SpinningCircle /&amp;gt;}
          {videosWatched.length &amp;gt; 0 &amp;amp;&amp;amp;
            !loading &amp;amp;&amp;amp;
            !error &amp;amp;&amp;amp;
            videosWatched.slice(0,2).map((video) =&amp;gt; (
              &amp;lt;div key={`${video.id}-${video.__typename}`} className="flex flex-col w-full  gap-4 rounded overflow-hidden"&amp;gt;
                &amp;lt;div className="aspect-video"&amp;gt;
                  &amp;lt;img alt="" src={video.thumbnailDefault ?? ''} className=" h-full w-full object-cover " /&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div&amp;gt; {sliceText({ s: video.title })}&amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            ))}
        &amp;lt;/div&amp;gt;

![ ](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1emd3dxxookrnnrypoi.png)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here we are splitting evenly the positive space of the parent component to each item. if we increase the window inner width, we want more items to be rendered. In this case, at full width of the innerWidth we would want 5 items to be displayed.&lt;/p&gt;

&lt;p&gt;The question is how can we do so while preventing from capturing every time user changes the width to make the application more optimal. One thing comes in mind is using a throttle function. Using a throttle function we can  prevent the event listener from being triggered multiple times. In addition, we could have an object with key and values where a key is the size of the width and the value is number of items to display.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const videosPerRowDisplayValues = {
  display_less_480: 1,
  display_481_699: 2,
  display_700_899: 2,
  display_900_1124: 3,
  display_1125_1420: 3,
  display_1421_1739: 4,
  display_1740_1920: 5,
  display_full: 5,
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with the object in place, we could pass as a prop to a hook where we would have a function that will call the window event listener for the inner width&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import { useEffect, useState } from 'react';
import { useThrottle } from './useThrottle.ts';

interface VideoGridProps {
  display_less_480?: number;
  display_481_699?: number;
  display_700_899?: number;
  display_900_1124?: number;
  display_1125_1420?: number;
  display_1421_1739?: number;
  display_1740_1920?: number;
  display_full?: number;
}

function getVideosPerRowFromWidth(props: VideoGridProps, width: number): number {
  const { display_less_480, display_481_699, display_700_899, display_900_1124, display_1125_1420, display_1421_1739, display_1740_1920, display_full } = props;

  if (width &amp;lt;= 480) return display_less_480 ?? 1;
  if (width &amp;gt;= 481 &amp;amp;&amp;amp; width &amp;lt;= 699) return display_481_699 ?? 1;
  if (width &amp;gt;= 700 &amp;amp;&amp;amp; width &amp;lt;= 899) return display_700_899 ?? 2;
  if (width &amp;gt;= 900 &amp;amp;&amp;amp; width &amp;lt;= 1124) return display_900_1124 ?? 3;
  if (width &amp;gt;= 1125 &amp;amp;&amp;amp; width &amp;lt;= 1420) return display_1125_1420 ?? 3;
  if (width &amp;gt;= 1421 &amp;amp;&amp;amp; width &amp;lt;= 1739) return display_1421_1739 ?? 4;
  if (width &amp;gt;= 1740 &amp;amp;&amp;amp; width &amp;lt;= 1920) return display_1740_1920 ?? 5;
  return display_full ?? 5;
}

export const useVideoGrid = (props: VideoGridProps): number =&amp;gt; {
  const [videosPerRow, setVideosPerRow] = useState&amp;lt;number&amp;gt;(() =&amp;gt; (typeof window !== 'undefined' ? getVideosPerRowFromWidth(props, window.innerWidth) : (props.display_full ?? 1)));

  const determineVideosToShow = () =&amp;gt; {
    setVideosPerRow(getVideosPerRowFromWidth(props, window.innerWidth));
  };

  const throttleVideosToShowPerRow = useThrottle(determineVideosToShow, 50);

  useEffect(() =&amp;gt; {
    const handleVideosToShow = () =&amp;gt; {
      throttleVideosToShowPerRow();
    };

    window.addEventListener('resize', handleVideosToShow);
    return () =&amp;gt; window.removeEventListener('resize', handleVideosToShow);
  }, [throttleVideosToShowPerRow]);

  return videosPerRow;
};


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useRef } from 'react';

export const useThrottle = &amp;lt;T extends (...args: any[]) =&amp;gt; void&amp;gt;(callBack: T, interval: number) =&amp;gt; {
  const lastExecuted = useRef&amp;lt;number&amp;gt;(0);

  return (...args: Parameters&amp;lt;T&amp;gt;) =&amp;gt; {
    const now = Date.now();

    if (now - lastExecuted.current &amp;lt; interval) return;

    lastExecuted.current = now;

    return callBack(...args);
  };
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We pass the object as a prop and we have a helper function that takes 2 parameters: the object  with the predetermined values for the width and the actual window width. Based on the condition statement we return a value. Fall back is 5 items.&lt;/p&gt;

&lt;p&gt;the custom hook useThrottle returns the call back  function. Here we wrapping in another function that wraps the determinedVideosToShow callback. We then call the function in the useEffect and use as a dependency; That way, it will be called whenever we have  a new value and the call back is only triggered within the interval declared in the throttle hook.&lt;/p&gt;

&lt;p&gt;Returning back to our component   we now can use the value returned by the hook&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const videosPerRow = useVideoGrid(videosPerRowDisplayValues);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    &amp;lt;div className="grid grid-flow-col  gap-4" style={{ gridTemplateColumns: `repeat(${videosPerRow}, 1fr) ` }}&amp;gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We now using a dynamic value to change the number of columns.&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%2F3ktaj67hj2a4yah42lb8.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%2F3ktaj67hj2a4yah42lb8.png" alt=" " width="800" height="521"&gt;&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%2F8e76rhxvsrf17v9nirev.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%2F8e76rhxvsrf17v9nirev.png" alt=" " width="800" height="564"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This will handle different width and devices&lt;/p&gt;

&lt;p&gt;Finally, we need now to implement the slicing logic. Supposedly we an array and the length of array does not matter but as the value not to go out of boundary. We starting from index 0 and what should be the end index ? Well, we know that the end index it should not be more than the length of array. If it is we simply return. If we use start index + videosPerRow we get the following&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EndIndex:= StartIndex + VideosPerRow&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;if start index is 0 and videos per row is 1 then start index will be 0 and end index will be one. So, we will be sliding one video at the time. Then we move the previous value of start index to the index of the endIndex and the end index to the value of the start index + VideosPer Row. That way, when we increment we will have a window slide of 1 video. And the slide depth will change accordingly to the number of videosPerRow&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  const [startIndex, setStartIndex] = useState&amp;lt;number&amp;gt;(0);

  const handleScrollUp = () =&amp;gt; {
    if (startIndex + videosPerRow &amp;gt;= videosWatched.length) return;

    setStartIndex(startIndex + videosPerRow);
  };

  const handleScrollDown = () =&amp;gt; {
    if (startIndex - videosPerRow &amp;lt; 0) return;
    setStartIndex(startIndex - videosPerRow);
  };


      &amp;lt;div className="grid grid-flow-col  gap-4" style={{ gridTemplateColumns: `repeat(${videosPerRow}, 1fr) ` }}&amp;gt;
          {loading &amp;amp;&amp;amp; &amp;lt;SpinningCircle /&amp;gt;}
          {videosWatched.length &amp;gt; 0 &amp;amp;&amp;amp;
            !loading &amp;amp;&amp;amp;
            !error &amp;amp;&amp;amp;
            videosWatched.slice(startIndex, startIndex + videosPerRow).map((video) =&amp;gt; (
              &amp;lt;div key={`${video.id}-${video.__typename}`} className="flex flex-col w-full  gap-4 rounded overflow-hidden"&amp;gt;
                &amp;lt;div className="aspect-video"&amp;gt;
                  &amp;lt;img alt="" src={video.thumbnailDefault ?? ''} className=" h-full w-full object-cover " /&amp;gt;
                &amp;lt;/div&amp;gt;
                &amp;lt;div&amp;gt; {sliceText({ s: video.title })}&amp;lt;/div&amp;gt;
              &amp;lt;/div&amp;gt;
            ))}
        &amp;lt;/div&amp;gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That resolves our problem and it allow us to slide through the content while maintaining an appealing interface and keeping the code optimal.&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%2Fdrbhokcnokji99j85maf.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%2Fdrbhokcnokji99j85maf.png" alt=" " width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;About Me:&lt;/p&gt;

&lt;p&gt;I am Mohamed Sharif and I have an undergraduate degree in computer science from San Francisco State University. I am currently starting a master degree towards machine learning and artificial intelligence through Drexel University. Since graduation I started to focus on full stack development. I enjoy writing blogs and currently implementing a full stack clone of youtube application. I reside in the San Francisco Bay area near silicon valley. I am open full full stack development roles. If you would like to connect, send me an invite on linkedin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/mohamed-sharif-47301520b/" rel="noopener noreferrer"&gt;My Linkedin Account&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>frontend</category>
      <category>programming</category>
    </item>
    <item>
      <title>Resolving Type Name Collisions with Graphene Django Filter and Enums</title>
      <dc:creator>Mohamed Sharif</dc:creator>
      <pubDate>Mon, 14 Jul 2025 06:17:50 +0000</pubDate>
      <link>https://dev.to/msharifhub/resolving-type-name-collisions-with-graphene-django-filter-and-enums-lh7</link>
      <guid>https://dev.to/msharifhub/resolving-type-name-collisions-with-graphene-django-filter-and-enums-lh7</guid>
      <description>&lt;p&gt;Introduction &lt;/p&gt;

&lt;p&gt;When using Graphene Django to build APIs on top of Django we might get typename collisions when using filter or models fields with choices. Usually the errors and warnings are:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TypeError: Found different types with the same name in the schema

UserWarning: The `filterset_class` argument without `filter_input_type_prefix` can result in different types with the same name in the schema. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Understanding the Problem:&lt;/p&gt;

&lt;p&gt;When using Grapehene Django filtering, it auto-generates Graphql Input types for each FilterSet you use. If you use the same filter class in multiple root-level query fields, it will create the same input type for both.&lt;/p&gt;

&lt;p&gt;Example&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
class PostFilter(django_filters.FilterSet):
    class Meta:
        model = Post
        fields = {'author': ['exact'], 'content': ['icontains']}


class Query(graphene.ObjectType):
    all_posts = AdvancedDjangoFilterConnectionField(PostNode)
    viewer_posts =AdvancedDjangoFilterConnectionField(PostNode)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code above will cause Django to throw an Assertion Error with Found different types with the same name in the schema. It will create a duplicate of PostNodeFilterInputType. When it converts a field with choices to a graphene.Enum, it creates a new type for this field&lt;/p&gt;

&lt;p&gt;Solutions&lt;br&gt;
GraphQl requires every type name to be unique. With graphene-django-filter now we can set filter_input_type_prefix for each field that uses the same filter class.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;ModelName&amp;gt;&amp;lt;FieldName&amp;gt;ChoicesEnum&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;on Settings&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GRAPHENE = {&lt;br&gt;
    "DJANGO_CHOICE_FIELD_ENUM_V3_NAMING": True,&lt;br&gt;
&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;On Query Class&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;class Query(MeQuery, graphene.ObjectType):
viewer_posts = AdvancedDjangoFilterConnectionField(PostNode,filter_input_type_prefix="viewer_posts")
    all_posts = AdvancedDjangoFilterConnectionField(PostNode,filter_input_type_prefix="all_posts") 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://chatgpt.com/c/686fb023-a58c-8003-979c-7dd9b5925f5c#:~:text=Graphene%2DDjango%20Filtering%20Docs" rel="noopener noreferrer"&gt;DjangoDocs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://pypi.org/project/graphene-django-filter/" rel="noopener noreferrer"&gt;graphene-django-filter onPyPi&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/mohamed-sharif-47301520b/" rel="noopener noreferrer"&gt;Connect with me on Linkedin&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Front End Development And Integration With Google API | Using Hooks, Throttle, And Dynamic Style.</title>
      <dc:creator>Mohamed Sharif</dc:creator>
      <pubDate>Sun, 20 Oct 2024 06:18:21 +0000</pubDate>
      <link>https://dev.to/msharifhub/front-end-development-and-integration-with-google-api-using-hooks-throttle-and-dynamic-style-3lp0</link>
      <guid>https://dev.to/msharifhub/front-end-development-and-integration-with-google-api-using-hooks-throttle-and-dynamic-style-3lp0</guid>
      <description>&lt;p&gt;This article can be better understood if you are an intermediate React and familiar with API Calls.&lt;/p&gt;

&lt;p&gt;In this article, I would like to go over in how to solve the problem of fetching only the videos that an user can see within the application UI. Basically, the problem is you have to fetch videos in a perfect matrix grid( rows and columns are the same). The challenge is that the number of rows and grids change as screen reduces. Mostly, only videos that can be fit in the grid it should be fetched. With this in mind we are implementing a dynamic UI where only a certain amount of videos are fetched within a screen size. And where do I come with this ? If you open the youtube application and set at full screen at home page you ll notice that the top sub grid have 5 rows and 5 columns and the number of videos change while maintaining an even distribution&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approach To The Problem:&lt;/strong&gt;&lt;br&gt;
Controlling the number of Videos to fetch And Implementing useYoutubeVideos Hook:&lt;br&gt;
When we call the Youtube API , provided by Google, we are able to add a max limit of videos to fetch by querying with "=". Having this ability to select max we can dynamically change the value to fit our needs. When we calling an API within our application where we expecting more than just saving the data, we can create a hook and in the hook we will handle all the functionality to handle the fetching and returning the state needed.&lt;/p&gt;

&lt;p&gt;Now, how are we going to implement the hook. First thing we need to know what is the form of data we are expected to receive. This is a must do and yes I am using Typecript. So, before get into the documentation the most common sense is that we want to return many videos and the a good data structure to store are arrays. Thus, we expecting Videos [] of type Videos but we have no idea what is the type Video. After exploring the documentation we learn that a video is&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
`{
  id: {
    videoId: string;
  };
  snippet: VideoSnippet;
} `

And Video snipped is 
`{
  title: string;
  description: string;
  thumbnails?: {
    default?: {
      url: string;
    };
    medium?: {
      url: string;
    };
    high?: {
      url: string;
    };
  };
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;there is nothing complex about the data structure for the api and we are given several options to the video thumbnails.&lt;/p&gt;

&lt;p&gt;In addition to this, were are given more parameters such loading and error. Another important functionality is we need to play a video but to play a video we need a function that gets the video id. Now, we can formulate our hook as a function, in this case we need to pass the API key from google console, and max results. But our result will be of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`{
  videos: Video[];
  loading: boolean;
  error: string | null;
  playVideo: (videoId: string) =&amp;gt; void;
  selectedVideoId: string | null;
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here videos is the array video or we can put as Array. We need to have loading to add some UI while loading, error to handle errors, play video and selected video to handle videos selected to play. Thus we will be returning the above to use later. We also need to set each as a state so we will be passing the state result. Mostly, we will be passing an async function to fetch and call only once using use effect. The loading is initially assume to be true and within the fetch function if we get a response status 200 then we can set loading to false. Here is the final hook implementation.&lt;br&gt;
_&lt;br&gt;
**Youtube API End Point: **&lt;a href="https://www.googleapis.com/youtube/v3/search?key=$%7BapiKey%7D&amp;amp;part=snippet&amp;amp;type=video&amp;amp;maxResults=$%7BmaxResult%7D,_" rel="noopener noreferrer"&gt;https://www.googleapis.com/youtube/v3/search?key=${apiKey}&amp;amp;part=snippet&amp;amp;type=video&amp;amp;maxResults=${maxResult},_&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;`useEffect, useState } from 'react';
import axios from 'axios';

export interface VideoSnippet {
  title: string;
  description: string;
  thumbnails?: {
    default?: {
      url: string;
    };
    medium?: {
      url: string;
    };
    high?: {
      url: string;
    };
  };
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export interface Video {
  id: {
    videoId: string;
  };
  snippet: VideoSnippet;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface UseYoutubeVideosResult {
  videos: Video[];
  loading: boolean;
  error: string | null;
  playVideo: (videoId: string) =&amp;gt; void;
  selectedVideoId: string | null;
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
export default function useYoutubeVideos(
  apiKey: string,
  maxResult: number,
): UseYoutubeVideosResult {
  const [videos, setVideos] = useState&amp;lt;Video[]&amp;gt;([]);
  const [loading, setLoading] = useState&amp;lt;boolean&amp;gt;(false);
  const [error, setError] = useState&amp;lt;string | null&amp;gt;(null);
  const [selectedVideoId, setSelectedVideoId] = useState&amp;lt;string | null&amp;gt;(null);

  function playVideo(videoId: string): void {
    setSelectedVideoId(videoId);
  }

  async function fetchVideos() {
    setLoading(true);
    setError(null);

    try {
      const response = await axios.get(
        `https://www.googleapis.com/youtube/v3/search?key=${apiKey}&amp;amp;part=snippet&amp;amp;type=video&amp;amp;maxResults=${maxResult}`,
      );

      if (response.status === 200) {
        setVideos(response.data.items);
      }
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  }

  useEffect(() =&amp;gt; {
    fetchVideos();
  }, []);

  return {
    videos,
    loading,
    error,
    playVideo,
    selectedVideoId,
  };
}`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Implementing UseVideoGrid hook:&lt;/strong&gt;&lt;br&gt;
The idea is to have hook that will check the width of screen and based on the width it will set the state to the number of videos per row. Here is where we would use a throttle function for performance. We will then be returning the state videos per row.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hook Implementation&lt;/strong&gt;&lt;br&gt;
The first step is to get the screen width with window.innerWidth and set a basic if and else condition where we will use a state videosPerRow  (5) default value set to 5.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [videosPerRow, setVideosPerRow] = useState&amp;lt;number&amp;gt;(5);

  const determineVideosToShow = () =&amp;gt; {
    const screenWidth = window.innerWidth;

    if (screenWidth &amp;lt;= 500) {
      setVideosPerRow(1); // 1 video per row on very small screens (2 rows total)
    } else if (screenWidth &amp;gt; 500 &amp;amp;&amp;amp; screenWidth &amp;lt;= 739) {
      setVideosPerRow(2); // 2 videos per row (2 rows total)
    } else if (screenWidth &amp;gt;= 740 &amp;amp;&amp;amp; screenWidth &amp;lt;= 1023) {
      setVideosPerRow(3); // 3 videos per row (2 rows total)
    } else if (screenWidth &amp;gt;= 1024 &amp;amp;&amp;amp; screenWidth &amp;lt;= 1279) {
      setVideosPerRow(4); // 4 videos per row (2 rows total)
    } else {
      setVideosPerRow(5); // 5 videos per row (2 rows total)
    }
  };
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we put the logic inside a nested function so we can call it inside the throttle as a call back function. I have set the time to 150 mile seconds to keep its responsiveness intact, otherwise, it will not be as responsive as needed when interacting with screen size.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; // Adding the throttle function here with 150 seconds time out
  const throttleVideosToShowPerRow  = useThrottle(determineVideosToShow, 150);

import { useEffect, useState } from 'react';
import { useThrottle } from './useThrottle.ts';

/**
 * @videosPerRow{number} return number of videos show per row.
 * @setVideosPerRow{void} function that uses screen width to set number of videos to show
 * @return is the number of videos per row to be used
 */
export const useVideoGrid = () =&amp;gt; {
  const [videosPerRow, setVideosPerRow] = useState&amp;lt;number&amp;gt;(5);

  const determineVideosToShow = () =&amp;gt; {
    const screenWidth = window.innerWidth;

    if (screenWidth &amp;lt;= 500) {
      setVideosPerRow(1); // 1 video per row on very small screens (2 rows total)
    } else if (screenWidth &amp;gt; 500 &amp;amp;&amp;amp; screenWidth &amp;lt;= 739) {
      setVideosPerRow(2); // 2 videos per row (2 rows total)
    } else if (screenWidth &amp;gt;= 740 &amp;amp;&amp;amp; screenWidth &amp;lt;= 1023) {
      setVideosPerRow(3); // 3 videos per row (2 rows total)
    } else if (screenWidth &amp;gt;= 1024 &amp;amp;&amp;amp; screenWidth &amp;lt;= 1279) {
      setVideosPerRow(4); // 4 videos per row (2 rows total)
    } else {
      setVideosPerRow(5); // 5 videos per row (2 rows total)
    }
  };

  // Adding the throttle function here with 150 seconds time out
  const throttleVideosToShowPerRow = useThrottle(determineVideosToShow, 150);

  // use effect to change the state whenever
  useEffect(() =&amp;gt; {
    throttleVideosToShowPerRow();

    const handleVideosToShow = () =&amp;gt; {
      throttleVideosToShowPerRow();
    };

    window.addEventListener('resize', handleVideosToShow);

    return () =&amp;gt; window.removeEventListener('resize', handleVideosToShow);
  }, [throttleVideosToShowPerRow]);

  return videosPerRow;
};
`
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;strong&gt;Putting All together&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Now, we are going to call these hooks in the component that represents the display for the videos. First, we will use a dummy_data before fetching the api since theres a limit to how much we can request per day.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
import dummy_videos from '../../../dummyData.json';
 // Using the useVideo hook to control number of videos show per screen size
  const videosPerRow = useVideoGrid();

  const totalVideosToShow = videosPerRow * 2;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The idea is that we want both rows to have same amount of videos so we multiply by 2 since we are dealing with only two rows&lt;/p&gt;

&lt;p&gt;We then call the youtube vidoes use hook and destruct elements we need to use&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const { videos, loading, error, playVideo, selectedVideoId } =
  useYoutubeVideos(api_key, totalVideosToShow);


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we then implement a functio to play videos by calling the deconstructed function from hoo,&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
function handleVideoClick(videoId: string) {
  playVideo(videoId);
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we add the dynamic values in the div for "gridTemplateColumns" we basically repeating columns per video per row and set min and max (0 as no videos and 1fr as 1 video. The main div holds 2 inner divs. One div where we have the grid layout for the videos and another div where we map the videos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (
    &amp;lt;&amp;gt;
      {/* Main Home Frame */}
      &amp;lt;div className="h-screen overflow-hidden flex justify-center items-start "&amp;gt;
        {!isLoggedIn &amp;amp;&amp;amp; &amp;lt;NotLoggedInBanner /&amp;gt;}

        {/* first row of videos */}
        &amp;lt;div
          className={` h-[600px] w-full  grid  grid-rows-2  gap-4 p-4  overflow-hidden `}
          style={{
            gridTemplateColumns: `repeat(${videosPerRow},minmax(0,1fr))`,
          }}
        &amp;gt;
          {dummy_videos.videos.slice(0, totalVideosToShow).map((video) =&amp;gt; (
            &amp;lt;div
              key={video.id.videoId}
              className="flex  flex-col justify-center items-center rounded-lg border "
            &amp;gt;
              {/*{selectedVideoId === id.videoId ? (*/}
              {/*  &amp;lt;iframe*/}
              {/*    width="560"*/}
              {/*    height="315"*/}
              {/*    src={`https://www.youtube.com/embed/${id.videoId}`}*/}
              {/*    allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"*/}
              {/*    allowFullScreen*/}
              {/*    title="YouTube Video Player"*/}
              {/*  &amp;gt;&amp;lt;/iframe&amp;gt;*/}
              {/*) : (*/}
              &amp;lt;img
                src={video.snippet.thumbnails?.default?.url}
                alt={video.snippet.title}
                onClick={() =&amp;gt; handleVideoClick(video.id.videoId)}
                className="invert pointer"
              /&amp;gt;
              {/*)}*/}
              &amp;lt;div className="font-bold text-lg  text-center"&amp;gt;
                {video.snippet.title}
              &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
          ))}
        &amp;lt;/div&amp;gt;
      &amp;lt;/div&amp;gt;
    &amp;lt;/&amp;gt;
  );
};

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The video play section is commented out and not part of this article. Yet, in the &lt;a href="" class="article-body-image-wrapper"&gt;&lt;img&gt;&lt;/a&gt; tag we setting the video thumbnails and to default size. Note we are only calling the amount of videos based on screen size. &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%2Fus5qj457gq4zr1nxnnl4.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%2Fus5qj457gq4zr1nxnnl4.png" alt=" " width="578" height="717"&gt;&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%2F7eawm7uicovxpwa4jxcu.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%2F7eawm7uicovxpwa4jxcu.png" alt=" " width="800" height="534"&gt;&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%2Funkl5ms9wy89rw4l2n4f.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%2Funkl5ms9wy89rw4l2n4f.png" alt=" " width="451" height="1173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alright, this is the end of the article. The functionality can be better and current one is causing some of videos to collapse but using CSS "flex-wrap" and "padding" we are able to fix this issue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who Am I
&lt;/h2&gt;

&lt;p&gt;My name is Sharif and I have a B.S degree in computer science. Since graduation, I have been mostly focus on full stack development. In addition, I like to solve algorithms questions like leet code. I have done few assessments by big tech companies and currently in the interview process, being as positive as I can. My next academic step in a near future is focus on machine learning since I am strong believer of using it to create apps with a vast arrays of functionalities. This article is part of my personal project where I am building a full stack clone of youtube. If you like my article please give me thumbs up. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.linkedin.com/in/mohamed-sharif-47301520b/" rel="noopener noreferrer"&gt;Lets Connect On Linkedin&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
