<?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: Matan Levi</title>
    <description>The latest articles on DEV Community by Matan Levi (@mlevi1806).</description>
    <link>https://dev.to/mlevi1806</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%2F689111%2Fc86ff177-c50d-4202-9819-511c4dbe34ff.jpg</url>
      <title>DEV Community: Matan Levi</title>
      <link>https://dev.to/mlevi1806</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mlevi1806"/>
    <language>en</language>
    <item>
      <title>The power of custom hooks in React (responsive design example)</title>
      <dc:creator>Matan Levi</dc:creator>
      <pubDate>Tue, 24 Aug 2021 20:44:17 +0000</pubDate>
      <link>https://dev.to/mlevi1806/the-power-of-custom-hooks-in-react-responsive-design-example-4flb</link>
      <guid>https://dev.to/mlevi1806/the-power-of-custom-hooks-in-react-responsive-design-example-4flb</guid>
      <description>&lt;p&gt;Generally, custom hook is a great pattern in order to handle modularity and composition in your app. you can write a custom hook for almost everything!&lt;/p&gt;

&lt;p&gt;BTW, if you're interested in custom hooks, I assume you are familiar with React hooks concept. if not, no worries, you can read about it &lt;a href="https://reactjs.org/docs/hooks-overview.html"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Something that worth to mention here (taken from React docs):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hooks are functions that let you “hook into” React state and lifecycle features from function components. Hooks don’t work inside classes — they let you use React without classes. (We don’t recommend rewriting your existing components overnight but you can start using Hooks in the new ones if you’d like.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/B4ZgcoPTHYXL2/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/B4ZgcoPTHYXL2/giphy.gif" alt='"Captain hook"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take responsive window handling as an example..&lt;/p&gt;

&lt;p&gt;The most common approach for responsive design is &lt;strong&gt;CSS media queries&lt;/strong&gt;, but in some cases, we will want to handle it via &lt;strong&gt;JavaScript&lt;/strong&gt; (conditionally render components, execute some logic when window size is changing to some point, etc.)&lt;/p&gt;

&lt;p&gt;In the example below you will see how we can use &lt;strong&gt;React hooks&lt;/strong&gt; for that purpose + compose code and reuse/share it across an app(s).&lt;/p&gt;

&lt;h3&gt;
  
  
  Some declarations
&lt;/h3&gt;

&lt;p&gt;Our custom hook is called &lt;code&gt;useResponsiveWindow&lt;/code&gt; and gets &lt;code&gt;sizes&lt;/code&gt; as an optional object.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Hook name convention is a &lt;code&gt;use&lt;/code&gt; prefix followed by a story telling, camel cased name (like &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useRef&lt;/code&gt;, &lt;code&gt;useContext&lt;/code&gt;, etc.)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Most of the apps use these common sizes which declared as a default using &lt;code&gt;DEFAULT_SIZES&lt;/code&gt;, but feel free to change or pass your own to the hook.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;DESKTOP_MIN&lt;/code&gt; size is also a standard minimum resolution for a desktop view (Again, not a taboo..). we will use it later.&lt;/p&gt;

&lt;p&gt;First, we will want to save state for first, on load, width &amp;amp; height using &lt;code&gt;useState&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const DEFAULT_SIZES = {
  small: [1366, 768],
  medium: [1400, 900],
  large: [1920, 1080],
  mobile: [360, 640]
};

export enum ResolutionState {
  XS = "Extra Small",
  SMALL = "Small",
  MEDIUM = "Medium",
  LARGE = "Large"
}

const DESKTOP_MIN = [1280, 720];

const useResponsiveWindow = (sizes = DEFAULT_SIZES) =&amp;gt; {
  const [width, setWidth] = useState(window.innerWidth);
  const [height, setHeight] = useState(window.innerHeight);
  const resizeTimer = useRef(null);

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Track window size and store it
&lt;/h3&gt;

&lt;p&gt;Adding resize event listener (remove it on unmount) and execute &lt;code&gt;handleWindowResize&lt;/code&gt; which will save the new values.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.....

  const handleWindowResize = useCallback((e) =&amp;gt; {
    clearTimeout(resizeTimer.current);
    resizeTimer.current = setTimeout(() =&amp;gt; {
      setWidth(e.target.innerWidth);
      setHeight(e.target.innerHeight);

    }, 200);

  }, [setWidth, setHeight, resizeTimer]);

  useEffect(() =&amp;gt; {
    window.addEventListener('resize',handleWindowResize);
    return () =&amp;gt; {
      window.removeEventListener('resize', handleWindowResize);
    };
  }, [handleWindowResize]);

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Useful insights
&lt;/h3&gt;

&lt;p&gt;Now that we have width, height and resolution thresholds, we get some insights that we can use in our application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;.....

  const resolutionState = useCallback((type) =&amp;gt; {
    const index = type === 'width' ? 0 : 1;
    const value = type === 'width' ? width : height;
    if(value &amp;gt;= sizes?.small[index] &amp;amp;&amp;amp; value &amp;lt; sizes?.medium[index]) {
      return ResolutionState.SMALL;
    } else if(value &amp;gt;= sizes?.medium[index] &amp;amp;&amp;amp; value &amp;lt; sizes?.large[index]) {
      return ResolutionState.MEDIUM;
    } else if(value &amp;gt;= sizes?.large[index]) {
      return ResolutionState.LARGE;
    } else {
      return ResolutionState.XS;
    }
  }, [width, height]);

  const widthState = resolutionState('width');
  const heightState = resolutionState('height');

  const isMobile = useMemo(() =&amp;gt; sizes?.mobile &amp;amp;&amp;amp; width &amp;lt;= sizes?.mobile[0] &amp;amp;&amp;amp; height &amp;lt;= sizes?.mobile[1], [width, height]);

  const isDesktop = useMemo(() =&amp;gt; width &amp;gt;= DESKTOP_MIN[0] &amp;amp;&amp;amp; height &amp;gt;= DESKTOP_MIN[1], [width, height]);

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Consuming the hook
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const SomeComponent= () =&amp;gt; {
  const {
    width,
    height,
    isMobile,
    isDesktop,
    widthState,
    heightState
  } = useResponsiveWindow();

  useEffect(() =&amp;gt; {
    console.log(`Width state now is: ${widthState}`);
    // do something here...
  }, [widthState]);

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;p&amp;gt;{`${width} (${widthState}) x ${height} (${heightState})`}&amp;lt;/p&amp;gt;
      {isMobile &amp;amp;&amp;amp; &amp;lt;div&amp;gt;Mobile View&amp;lt;/div&amp;gt;}
      {isDesktop &amp;amp;&amp;amp; &amp;lt;div&amp;gt;Desktop View&amp;lt;/div&amp;gt;}
    &amp;lt;/div&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can view an example &lt;a href="https://react-ts-8gfbuo.stackblitz.io"&gt;here&lt;/a&gt; and the source code here:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://stackblitz.com/edit/react-ts-8gfbuo?embed=1&amp;amp;&amp;amp;" width="100%" height="500"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;There are many libraries providing many custom hooks as a solution, and probably your app has a lot of those, but try to find some that you can implement yourself, it will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;saves you bundle size.&lt;/li&gt;
&lt;li&gt;gives you a full control of your code.&lt;/li&gt;
&lt;li&gt;extend your code skills outside app borders, into the infra zone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;About this hook - it's  not perfect, and probably able to offer much more insights and useful data, according to your needs.&lt;/p&gt;

&lt;p&gt;Suggestions and thought are more than welcome :)&lt;/p&gt;

&lt;p&gt;Image by &lt;a href="https://pixabay.com/users/terimakasih0-624267/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=2309593"&gt;Dean Moriarty&lt;/a&gt; from &lt;a href="https://pixabay.com/?utm_source=link-attribution&amp;amp;utm_medium=referral&amp;amp;utm_campaign=image&amp;amp;utm_content=2309593"&gt;Pixabay&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
