<?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>Forem: Rashid Shamloo</title>
    <description>The latest articles on Forem by Rashid Shamloo (@rashidshamloo).</description>
    <link>https://forem.com/rashidshamloo</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%2F1029147%2F2afb1506-8d9d-45ba-997d-285a68af23a1.png</url>
      <title>Forem: Rashid Shamloo</title>
      <link>https://forem.com/rashidshamloo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rashidshamloo"/>
    <language>en</language>
    <item>
      <title>API Data Fetching in React / Next.js</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Wed, 03 Jan 2024 18:20:22 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/api-data-fetching-in-react-nextjs-289d</link>
      <guid>https://forem.com/rashidshamloo/api-data-fetching-in-react-nextjs-289d</guid>
      <description>&lt;p&gt;Remember the good old days when you could just use a &lt;code&gt;UseEffect()&lt;/code&gt; hook, define an async function with &lt;code&gt;useCallback()&lt;/code&gt; and call it inside &lt;code&gt;useEffect()&lt;/code&gt;, use an &lt;code&gt;AbortController()&lt;/code&gt; to abort the fetch when the component unmounts, use &lt;code&gt;useState()&lt;/code&gt; to make the &lt;code&gt;isLoading&lt;/code&gt; and &lt;code&gt;isError&lt;/code&gt; states and manage them inside your &lt;code&gt;try-catch&lt;/code&gt;, and call it a week?&lt;/p&gt;

&lt;p&gt;Nowadays there are more ways to fetch your data and display it inside your component.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Fetching on the Client
&lt;/h2&gt;

&lt;p&gt;Before the introduction of Server Components and Server Actions, all data fetching had to be done on the client. If you needed to hide sensitive information like API keys, you had to have another API between the client and the final API endpoint that fetched the data using the API key and sent it to the client.&lt;/p&gt;

&lt;h3&gt;
  
  
  1-1. useEffect() + useState()
&lt;/h3&gt;

&lt;p&gt;This is the old way of doing it described at the start. the downside is that you have to write everything yourself (you have to add caching and re-fetching on top of everything mentioned already).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;useCallback&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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;MyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Data&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="dl"&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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&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;false&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;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsError&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;false&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;getData&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="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&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;setIsLoading&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="nf"&gt;setIsError&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;try&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;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;url&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="nx"&gt;signal&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;resJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="nf"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resJson&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setIsError&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="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="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;else&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;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&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="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setIsLoading&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="p"&gt;[]&lt;/span&gt;
  &lt;span class="p"&gt;);&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;getData&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&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;getData&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;Notes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since the code placed inside the main body of a functional component is executed on every update, we need to use &lt;code&gt;useEffect()&lt;/code&gt; to fetch the data only when the component is mounted.&lt;/li&gt;
&lt;li&gt;Because we can only use &lt;code&gt;await&lt;/code&gt; inside an &lt;code&gt;async&lt;/code&gt; function, and &lt;code&gt;useEffect()&lt;/code&gt; can't be &lt;code&gt;async&lt;/code&gt;, we need to define a separate &lt;code&gt;async&lt;/code&gt; function to get the data and call it inside &lt;code&gt;useEffect()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We can define the &lt;code&gt;async&lt;/code&gt; &lt;code&gt;getData()&lt;/code&gt; function inside the &lt;code&gt;useEffect()&lt;/code&gt; itself, but if we want to define it separately, we need to use &lt;a href="https://react.dev/reference/react/useCallback"&gt;&lt;code&gt;useCallBack()&lt;/code&gt;&lt;/a&gt;. Otherwise, the function will be re-created on every component update and since it's the dependency of the &lt;code&gt;useEffect()&lt;/code&gt; it will cause it to re-run on every update as well.&lt;/li&gt;
&lt;li&gt;Since a component may be mounted/unmounted many times, we need to abort the previous running fetch request when the component unmounts using an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/AbortController"&gt;AbortController&lt;/a&gt; and returning a function that aborts the controller from &lt;code&gt;useEffect()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  1-2. Data Fetching Libraries
&lt;/h3&gt;

&lt;p&gt;There are libraries like &lt;a href="https://swr.vercel.app/"&gt;SWR&lt;/a&gt;, &lt;a href="https://redux-toolkit.js.org/rtk-query/overview"&gt;RTK Query&lt;/a&gt;, and &lt;a href="https://tanstack.com/query/latest"&gt;React Query&lt;/a&gt; that simplify the data fetching process on the client and take care of the state, error handling, caching, and re-fetching for you.&lt;/p&gt;

&lt;p&gt;RTK Query example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;useGetDataQuery&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;path/to/apiSlice&lt;/span&gt;&lt;span class="dl"&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;MyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetDataQuery&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Fetching on the server
&lt;/h2&gt;

&lt;p&gt;Server Components and Server Actions allow data fetching and processing to be run on the server. The final result is sent to the client for display hiding all sensitive information and allowing for server caching of the data. This is the new paradigm in the React ecosystem.&lt;/p&gt;

&lt;h3&gt;
  
  
  2-1. Server Components
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/app/building-your-application/rendering/server-components"&gt;Server Components&lt;/a&gt; run on the server and unlike client components, can be &lt;code&gt;async&lt;/code&gt; and directly (without the need for &lt;code&gt;useEffect()&lt;/code&gt;) &lt;code&gt;await&lt;/code&gt; and &lt;code&gt;fetch&lt;/code&gt; the data and send the final result to the client. on top of the previously mentioned advantages of fetching on the server, this allows for patterns like &lt;a href="https://nextjs.org/learn/dashboard-app/partial-prerendering"&gt;Partial Prerendering&lt;/a&gt; where part of the page can be static and only the server components that need to fetch the data can be dynamically streamed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;MyComponent&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="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;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;data&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;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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&amp;gt;&lt;/span&gt;&lt;span class="err"&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="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since the component itself is fetching the data and takes time to render, you can use &lt;a href="https://react.dev/reference/react/Suspense"&gt;Suspense&lt;/a&gt; in the parent to display a loading indicator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;Suspense&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&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;./MyComponent&lt;/span&gt;&lt;span class="dl"&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;ParentComponent&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="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;Suspense&lt;/span&gt; &lt;span class="nx"&gt;fallback&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&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="sr"&gt;/Suspense&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ParentComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For error handling, You can use an &lt;a href="https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary"&gt;Error Boundary&lt;/a&gt;. By adding a &lt;a href="https://nextjs.org/docs/app/building-your-application/routing/error-handling"&gt;&lt;code&gt;Error.tsx&lt;/code&gt;&lt;/a&gt;&lt;br&gt;
 file to your app directory, Next.js automatically creates an error boundary, sets that component as the fallback, and lets you handle your errors easily.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;Note:&lt;/strong&gt; You can also handle the errors using a  &lt;code&gt;try-catch&lt;/code&gt; in your server component.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  2-2. Server Actions
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions-and-mutations"&gt;Server Actions&lt;/a&gt; are functions that run on the server and can be used to fetch data or perform any other task. The main benefit of Server Actions is that they can be called from client components. This gives you fine-grain control to choose which part of your code you want to run only on the server.&lt;/p&gt;

&lt;p&gt;When running Server Actions in Server Components, you just need to add the &lt;code&gt;'use server'&lt;/code&gt; directive to the function declaration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;getData&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&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;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;MyComponent&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;data&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;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getData&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;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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&amp;gt;&lt;/span&gt;&lt;span class="err"&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="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you want to use a Server Action in a client component, you need to move the function to a separate file, add the &lt;code&gt;'use server'&lt;/code&gt; directive at the top, and import and use it in your client component.&lt;/p&gt;

&lt;p&gt;Server Action (&lt;code&gt;getDataOnServer.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&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;getDataOnServer&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="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;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&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="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&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;Client Component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;getDataOnServer&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="s1"&gt;./getDataOnServer&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&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;getDataOnServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's modify our previous &lt;code&gt;useEffect() + useState()&lt;/code&gt; client component to fetch the data using a Server Action instead. We have to move the &lt;code&gt;try-catch&lt;/code&gt; error handling to the Server Action instead since the error will be thrown on the server, not on the client.&lt;/p&gt;

&lt;p&gt;Server Action (&lt;code&gt;getDataOnServer.ts&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getDataOnServer&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;data&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;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;try&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;res&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;url&lt;/span&gt;&lt;span class="dl"&gt;"&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;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&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="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&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;e&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error&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="k"&gt;return&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;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&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;Client Component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&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;getDataOnServer&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;./getDataOnServer&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;useCallback&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&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;ClientMyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setData&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Data&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;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setError&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="dl"&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;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsLoading&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;false&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;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsError&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;false&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;getData&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="k"&gt;async &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;setIsLoading&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&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;getDataOnServer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;setIsLoading&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;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;isError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setData&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="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setIsError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nf"&gt;setError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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="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="nf"&gt;getData&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;getData&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&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="nx"&gt;isError&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&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;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ClientMyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Warning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can't pass objects like an AbortSignal to a Server Action so we can't abort the fetch request on component unmount.&lt;/li&gt;
&lt;li&gt;Server Actions are usually used for data mutation, for fetching and displaying the data, Server Components are a better option.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;ℹ️ &lt;strong&gt;Note:&lt;/strong&gt; You can also use the &lt;a href="https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary"&gt;Error Boundary&lt;/a&gt; (&lt;a href="https://nextjs.org/docs/app/building-your-application/routing/error-handling"&gt;&lt;code&gt;Error.tsx&lt;/code&gt;&lt;/a&gt;) approach for handling errors.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  - Validation
&lt;/h3&gt;

&lt;p&gt;In all the examples above we're blindly setting our data to the result of &lt;code&gt;res.json()&lt;/code&gt; which is of type &lt;code&gt;any&lt;/code&gt;. This is not a good practice especially if you're fetching data from a third-party API.&lt;/p&gt;

&lt;p&gt;Before using the result of our fetch request, we need to verify that it is in the format we expect. To do that we can use a validation library like &lt;a href="https://zod.dev/"&gt;Zod&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We first make the schema for the data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;z&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;zod&lt;/span&gt;&lt;span class="dl"&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;dataSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&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;Then we can use the &lt;code&gt;parse()&lt;/code&gt; or &lt;code&gt;safeParse()&lt;/code&gt; methods to validate our data:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;resJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// will throw an error if parse() fails&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resJson&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// will not throw an error&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parseResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dataSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resJson&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;parseResult&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&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;=&lt;/span&gt; &lt;span class="nx"&gt;parseResult&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="k"&gt;else&lt;/span&gt;
  &lt;span class="c1"&gt;// handle error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;Note:&lt;/strong&gt; Parsing the API response with Zod also throws away any extra JSON data that is not in your schema and only returns the needed data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  - API Routes
&lt;/h3&gt;

&lt;p&gt;While you can use &lt;a href="https://nextjs.org/docs/pages/building-your-application/routing/api-routes"&gt;Next.js API Routes&lt;/a&gt; to fetch data on the server, it's not a separate way of doing it. they're just an API endpoint. you still have to make a fetch request and get the result from your API Route inside your component.&lt;/p&gt;




&lt;p&gt;Because RSC (React Server Components) and Server Actions are a new addition, there are some compatibility issues with some packages and libraries but they are getting updated and new workarounds are being implemented as we move forward.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>nextjs</category>
      <category>api</category>
    </item>
    <item>
      <title>React Native setup with Expo Router, NativeWind, and TypeScript</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Fri, 20 Oct 2023 03:18:45 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/react-native-setup-with-expo-router-nativewind-and-typescript-27ba</link>
      <guid>https://forem.com/rashidshamloo/react-native-setup-with-expo-router-nativewind-and-typescript-27ba</guid>
      <description>&lt;h3&gt;
  
  
  Table of Contents
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;React Native&lt;/li&gt;
&lt;li&gt;Expo&lt;/li&gt;
&lt;li&gt;Running your application on your phone&lt;/li&gt;
&lt;li&gt;Routing in Expo&lt;/li&gt;
&lt;li&gt;NativeWind&lt;/li&gt;
&lt;li&gt;Path Alias (@)&lt;/li&gt;
&lt;li&gt;Environment Variables&lt;/li&gt;
&lt;li&gt;Icons&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - React Native
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://reactnative.dev/"&gt;React Native&lt;/a&gt; lets you develop native mobile applications using &lt;a href="https://react.dev/"&gt;React&lt;/a&gt;. You will have to use different elements like &lt;code&gt;View&lt;/code&gt;, &lt;code&gt;Text&lt;/code&gt;, and &lt;code&gt;TouchOpacity&lt;/code&gt; instead of &lt;code&gt;div&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, and &lt;code&gt;button&lt;/code&gt; but the underlying logic is the same and you can apply what you already know about React like different hooks (&lt;code&gt;useState()&lt;/code&gt;, &lt;code&gt;useEffect()&lt;/code&gt;, etc.) or different libraries like &lt;a href="https://redux-toolkit.js.org/"&gt;Redux Toolkit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In this article, I will explain the steps you need to take to have a working setup so you can start developing using React Native.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - Expo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://expo.dev/"&gt;Expo&lt;/a&gt; to React Native is what &lt;a href="https://nextjs.org"&gt;Next.js&lt;/a&gt; is to React. it's a framework that provides all the necessary utilities you need for making a modern React Native application like Development Server, Routing, etc.&lt;/p&gt;

&lt;p&gt;Expo also offers a file-based routing very similar to the one offered by Next.js.&lt;/p&gt;

&lt;p&gt;To install Expo with file-based routing and TypeScript support, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-expo-app --template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when prompted to choose a template, select the &lt;code&gt;Navigation (TypeScript)&lt;/code&gt; template.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - Running your application on your phone
&lt;/h2&gt;

&lt;p&gt;To run the dev server you can use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You will be presented with a QR code and addresses you can enter manually to connect to the dev server.&lt;/p&gt;

&lt;p&gt;Next, Install the &lt;a href="https://play.google.com/store/apps/details?id=host.exp.exponent&amp;amp;hl=en&amp;amp;gl=US"&gt;Expo app&lt;/a&gt; on your phone, open it, and scan the QR code to connect to the dev server, and interact with your application.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;On Windows, you need to open the &lt;code&gt;8081&lt;/code&gt; port in your firewall. (allow it in the &lt;code&gt;Inbound Rules&lt;/code&gt; if you're using the default Windows firewall)&lt;/li&gt;
&lt;li&gt;You can also use the &lt;a href="https://developer.android.com/studio/run/emulator"&gt;Android Emulator&lt;/a&gt; in &lt;a href="https://developer.android.com/studio"&gt;Android Studio&lt;/a&gt; to test your application.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - Routing in Expo
&lt;/h2&gt;

&lt;p&gt;Similar to the file-based routing in Next.js (app directory), You can make new directories in the &lt;code&gt;app&lt;/code&gt; directory to present new routes or use dynamic routes like &lt;code&gt;[id]&lt;/code&gt; as well.&lt;/p&gt;

&lt;p&gt;An example setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/app
  /books
    /index.tsx
  /book
    /[id].tsx
  /_layout.tsx
  /index.tsx 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can use the &lt;code&gt;useRouter()&lt;/code&gt; hook to access the router and push a new path to it to navigate to another page.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;Text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TouchableOpacity&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="s1"&gt;react-native&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;useRouter&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="s1"&gt;expo-router&lt;/span&gt;&lt;span class="dl"&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;MyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRouter&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;TouchableOpacity&lt;/span&gt; &lt;span class="nx"&gt;onPress&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="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/books&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Text&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Show&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="nx"&gt;books&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Text&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;/TouchableOpacity&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - NativeWind
&lt;/h2&gt;

&lt;p&gt;You've most likely worked with or at least heard about &lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt;. It allows you to use pre-defined class names to add CSS rules to your elements instead of writing new classes yourself or using the &lt;code&gt;style&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.nativewind.dev/"&gt;NativeWind&lt;/a&gt; lets you use Tailwind CSS classes in React Native and can simplify and speed up the styling process. Especially if you've worked with Tailwind CSS before.&lt;/p&gt;

&lt;p&gt;In order to add NativeWind to your project, follow these steps:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install NativeWind using the following commands:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i nativewind
npm i -D tailwindcss
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Edit the &lt;code&gt;tailwind.config.js&lt;/code&gt; file and add the directories containing your &lt;code&gt;tsx&lt;/code&gt; files to the &lt;code&gt;content&lt;/code&gt; array:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;content: ['./app/**/*.{js,jsx,ts,tsx}', './components/**/*.{js,jsx,ts,tsx}'],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Edit the &lt;code&gt;babel.config.js&lt;/code&gt; file and add &lt;code&gt;'nativewind/babel'&lt;/code&gt; to the &lt;code&gt;plugins&lt;/code&gt; array:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins: [
  ...,
  'nativewind/babel',
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: If you've not installed Expo using the mentioned template and are getting the &lt;code&gt;No overload matches this call.&lt;/code&gt; error when adding the &lt;code&gt;className&lt;/code&gt; property to your elements, Add a &lt;code&gt;.d.ts&lt;/code&gt; file like &lt;code&gt;app.d.ts&lt;/code&gt; to the root of your project and add the following line to it:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/// &amp;lt;reference types="nativewind/types" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;You can also use this line instead:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/// &amp;lt;reference types="expo-router/types" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - Path Alias (@)
&lt;/h2&gt;

&lt;p&gt;When importing components from within nested components, instead of using &lt;code&gt;../../../components/Component&lt;/code&gt;, it's better to use a path alias that points to the root of your project like &lt;code&gt;@&lt;/code&gt;, and shorten your import paths using it like &lt;code&gt;@/components/Component&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Next.js already has this setup out of the box but for Expo, you need to add it manually.&lt;/p&gt;

&lt;p&gt;First, open your &lt;code&gt;tsconfig.json&lt;/code&gt; file and add the following line to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"compilerOptions": { "paths": { "@/*": ["./*"] } },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next, open the &lt;code&gt;app.json&lt;/code&gt; file and enable the experimental &lt;code&gt;tsconfigPaths&lt;/code&gt; feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "expo": {
    "experiments": { "tsconfigPaths": true }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the &lt;code&gt;@&lt;/code&gt; path alias to shorten your paths.&lt;/p&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - Environment Variables
&lt;/h2&gt;

&lt;p&gt;When storing sensitive information like API keys, you need to store them in a &lt;code&gt;.env&lt;/code&gt; file so you can use it in production but don't push it to GitHub and leak your API key. It also allows you to manage the information easier.&lt;/p&gt;

&lt;p&gt;In Expo like Next.js, you can achieve this using a &lt;code&gt;.env.local&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;EXPO_PUBLIC_API_KEY=0123456789
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can then access the variable in your app using:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;process.env.EXPO_PUBLIC_API_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Environment variables are stored as plain text and can still be accessed by end users. if you want to hide something from end users, you would need to use an &lt;em&gt;Orchestration Layer&lt;/em&gt; (an API or serverless function acting as a middle-man between your application and the final API) but it's out of the scope of this article.&lt;/li&gt;
&lt;li&gt;If you're using an older version of Expo that does not support environment variables by default, you can use the &lt;a href="https://www.npmjs.com/package/react-native-dotenv"&gt;&lt;code&gt;react-native-dotenv&lt;/code&gt;&lt;/a&gt; package.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  - Icons
&lt;/h2&gt;

&lt;p&gt;To add icons to your React Native application, you can use the &lt;code&gt;@expo/vector-icons&lt;/code&gt; package (installed by default). it comes with many different icons and should cover all your needs. to see a list of available icons and how to add them to your project, check this website: &lt;a href="https://icons.expo.fyi/"&gt;icons.expo.fyi&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;🎉 You should now have a working setup and can start developing your first application!&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>tutorial</category>
      <category>reactnative</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>Media Queries and Responsive Design</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Thu, 14 Sep 2023 13:39:46 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/media-queries-and-responsive-design-4efa</link>
      <guid>https://forem.com/rashidshamloo/media-queries-and-responsive-design-4efa</guid>
      <description>&lt;p&gt;Table of Contents&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Introduction
&lt;/li&gt;
&lt;li&gt;2. CSS

&lt;ul&gt;
&lt;li&gt;Using min-width and max-width&lt;/li&gt;
&lt;li&gt;Using the new range syntax&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;3. Styled-Components
&lt;/li&gt;
&lt;li&gt;4. Tailwind CSS
&lt;/li&gt;
&lt;li&gt;5. Material UI
&lt;/li&gt;
&lt;li&gt;6. JavaScript
&lt;/li&gt;
&lt;li&gt;7. React

&lt;ul&gt;
&lt;li&gt;window.matchMedia()&lt;/li&gt;
&lt;li&gt;Custom Hooks&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;8. An example
&lt;/li&gt;
&lt;li&gt;9. Tips and Tricks

&lt;ul&gt;
&lt;li&gt;Responsive font size&lt;/li&gt;
&lt;li&gt;Dealing with the impossible&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;10. Conclusion
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;1. Introduction
&lt;/h2&gt;

&lt;p&gt;With an &lt;a href="https://www.statista.com/statistics/277125/share-of-website-traffic-coming-from-mobile-devices/"&gt;ever-growing number of users&lt;/a&gt; using mobile devices to browse the internet, responsive design is a necessity.&lt;/p&gt;

&lt;p&gt;However, The layout for a large horizontal screen (desktop) can be  quite different from the layout for a small vertical screen (mobile). We may need to change the flow of elements, resize or hide some elements, and maybe even change the number and position of elements displayed. &lt;/p&gt;

&lt;p&gt;We can achieve all that with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries"&gt;Media Queries&lt;/a&gt;. Media Queries allow us to apply different CSS rules for different screen sizes (and other device characteristics like the pointer type or orientation).&lt;/p&gt;

&lt;p&gt;There are different ways of using Media Queries based on the CSS framework you're using. You can also use them in JavaScript or React to apply different logic for different screen sizes.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;2. CSS
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Using min-width and max-width
&lt;/h3&gt;

&lt;p&gt;By putting your CSS rules inside a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@media"&gt;&lt;code&gt;@media&lt;/code&gt;&lt;/a&gt; block, they will only apply when the specified condition (Media Query) is met:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * these rules will only apply when the screen width
   * is *greater* than or equal to 768px
   */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * these rules will only apply when the screen width
   * is *less* than or equal to 768px
   */&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 also use both &lt;code&gt;min-width&lt;/code&gt; and &lt;code&gt;max-width&lt;/code&gt; to target the screen sizes that fall in that range:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;min-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;480px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max-width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * these rules will only apply when the screen width
   * is *greater* than or equal to 480px and
   * is *less* than or equal to 768px
   */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Using the new range syntax
&lt;/h3&gt;

&lt;p&gt;There is a newer &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_media_queries/Using_media_queries#syntax_improvements_in_level_4"&gt;range syntax&lt;/a&gt; you can use to more easily write your media queries:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="err"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * these rules will only apply when the screen width
   * is *greater* than or equal to 768px
   */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * these rules will only apply when the screen width
   * is *less* than or equal to 768px
   */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;@media&lt;/span&gt; &lt;span class="n"&gt;screen&lt;/span&gt; &lt;span class="n"&gt;and&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;480px&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;width&lt;/span&gt; &lt;span class="err"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="m"&gt;768px&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;/* 
   * these rules will only apply when the screen width
   * is *greater* than or equal to 480px and
   * is *less* than or equal to 768px
   */&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;3. Styled-Components
&lt;/h2&gt;

&lt;p&gt;You can use Media Queries in &lt;a href="https://styled-components.com/"&gt;Styled-Components&lt;/a&gt; similar to how you would use them in CSS, other than the fact that you can define custom screen sizes in your theme and access them inside your Media Queries:&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;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;sm&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;600px&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;MyComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  @media screen and (min-width: &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sm&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;4. Tailwind CSS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://tailwindcss.com/"&gt;Tailwind CSS&lt;/a&gt; has multiple pre-defined &lt;a href="https://tailwindcss.com/docs/screens"&gt;screen sizes (breakpoints)&lt;/a&gt; that are compiled to the relevant Media Query (e.g. &lt;code&gt;md&lt;/code&gt; will compile to &lt;code&gt;@media (min-width: 768px) { ... }&lt;/code&gt;). You can use these breakpoints to easily apply different styles for different screen sizes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;class=&lt;/span&gt;&lt;span class="s"&gt;"text-white md:text-black"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!--
  The text color will be white for screen widths
  less than 768px and will be black for screen widths
  greater than or equal to 768px
--&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can customize the pre-defined screen sizes or add new ones by modifying the &lt;code&gt;tailwind.config.js&lt;/code&gt; file:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;800px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// 'md' will now be @media (min-width: 800px) { ... }&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;850px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="c1"&gt;// you can now use the new 'customName' breakpoint&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to use &lt;code&gt;max-width&lt;/code&gt; instead of &lt;code&gt;min-width&lt;/code&gt; or target a range, you can use the &lt;code&gt;max&lt;/code&gt; and &lt;code&gt;min&lt;/code&gt; properties:&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="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;max&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;800px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// 'md' will now be @media (max-width: 800px) { ... }&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;customName&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;min&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;850px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;max&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;900px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="c1"&gt;// the new 'customName' breakpoint will be&lt;/span&gt;
        &lt;span class="c1"&gt;// @media (min-width: 850px) and (max-width: 900px) { ... },&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;You can also use the &lt;code&gt;raw&lt;/code&gt; property to pass in a custom Media Query:&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;raw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(min-width: 800px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: When you add the &lt;code&gt;screens&lt;/code&gt; directly to the &lt;code&gt;theme&lt;/code&gt; object, it replaces the default &lt;code&gt;screens&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// default screens will be replaced by this&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;blockquote&gt;
&lt;p&gt;If you want to add or modify a breakpoint while preserving the default &lt;code&gt;screens&lt;/code&gt;, you should add your &lt;code&gt;screens&lt;/code&gt; to the &lt;code&gt;theme.extend&lt;/code&gt; object:&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;screens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// These will be applied in addition to the default screens&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;5. Material UI
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://mui.com/"&gt;Material UI&lt;/a&gt; has its own set of &lt;a href="https://mui.com/material-ui/customization/breakpoints/#default-breakpoints"&gt;breakpoints&lt;/a&gt; that can be &lt;a href="https://mui.com/material-ui/customization/breakpoints/#custom-breakpoints"&gt;customized in your theme&lt;/a&gt;. You can use them inside the &lt;a href="https://mui.com/system/getting-started/the-sx-prop/"&gt;sx prop&lt;/a&gt; to customize your styles for different screen sizes:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt;
  &lt;span class="nx"&gt;sx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{{&lt;/span&gt; 
    &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;xs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&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="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, these will compile to &lt;code&gt;min-width&lt;/code&gt; but Material UI also provides &lt;a href="https://mui.com/material-ui/customization/breakpoints/#css-media-queries"&gt;helpers&lt;/a&gt; you can use to target a range or use &lt;code&gt;max-width&lt;/code&gt; instead:&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Box&lt;/span&gt;
  &lt;span class="nx"&gt;sx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;theme&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;down&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&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="c1"&gt;// @media (max-width: 900px)&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;white&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;breakpoints&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;between&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;md&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lg&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="c1"&gt;// @media (min-width: 900px) and (max-width: 1200px)&lt;/span&gt;
      &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;black&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="p"&gt;})}&lt;/span&gt;
&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;6. JavaScript
&lt;/h2&gt;

&lt;p&gt;Sometimes you want to know the screen size in your JavaScript code and change your logic based on it. You can use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia"&gt;&lt;code&gt;window.matchMedia()&lt;/code&gt;&lt;/a&gt; method for that.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;window.matchMedia()&lt;/code&gt; returns an object with a &lt;code&gt;matches&lt;/code&gt; property which is either &lt;code&gt;true&lt;/code&gt; or &lt;code&gt;false&lt;/code&gt; depending on whether the document matches the Media Query or not.&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;isLarge&lt;/span&gt; &lt;span class="o"&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;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;(min-width: 1024px)&lt;/span&gt;&lt;span class="dl"&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;isLarge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// do something if screen width is larger than 1024px&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="c1"&gt;// do something else if it's not&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the value is only calculated when you run your code for the first time. if you want to react to screen size changes (window resize), you need to add an event listener for the &lt;code&gt;change&lt;/code&gt; event:&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;isLarge&lt;/span&gt; &lt;span class="o"&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;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(min-width: 1024px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;isLarge&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="s1"&gt;change&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="o"&gt;=&amp;gt;&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="nx"&gt;isLarge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;7. React
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- window.matchMedia()
&lt;/h3&gt;

&lt;p&gt;In React you can use the previously mentioned &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/matchMedia"&gt;&lt;code&gt;window.matchMedia()&lt;/code&gt;&lt;/a&gt; method:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&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;MyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLarge&lt;/span&gt; &lt;span class="o"&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;matchMedia&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(min-width: 1024px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&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;handleChange&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="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="nx"&gt;isLarge&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="nx"&gt;isLarge&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="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleChange&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isLarge&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="s1"&gt;change&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleChange&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Custom Hooks
&lt;/h3&gt;

&lt;p&gt;There are NPM packages like &lt;a href="https://www.npmjs.com/package/react-responsive"&gt;react-responsive&lt;/a&gt; that provide custom hooks for easy usage of Media Queries:&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMediaQuery&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="s1"&gt;react-responsive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLarge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMediaQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(min-width: 1024px)&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="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="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="nx"&gt;isLarge&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;isLarge&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;blockquote&gt;
&lt;p&gt;Note: &lt;a href="https://www.npmjs.com/package/react-responsive"&gt;react-responsive&lt;/a&gt; uses &lt;a href="https://www.npmjs.com/package/matchmediaquery"&gt;matchmediaquery&lt;/a&gt; which itself uses &lt;code&gt;window.matchMedia()&lt;/code&gt; under the hood.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you're using Material UI, it also provides a custom &lt;a href="https://mui.com/material-ui/react-use-media-query/"&gt;&lt;code&gt;useMediaQuery()&lt;/code&gt;&lt;/a&gt; hook you can use so you don't need to install any extra packages:&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="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMediaQuery&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="s1"&gt;@mui/material/useMediaQuery&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isLarge&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMediaQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;(min-width: 1024px)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&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="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="nx"&gt;isLarge&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;isLarge&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;8. An example
&lt;/h2&gt;

&lt;p&gt;This is a small section of my portfolio that I'm working on atm, and I liked how customized/different I could make it look on various screen sizes so I decided to write this article to share my knowledge:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/epJOR93viT0"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;In this example (ignoring the navigation menu and text) for different screen sizes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The size of the container element and images are changed&lt;/li&gt;
&lt;li&gt;The aspect ratio of the container element is changed while the images keep their aspect ratio&lt;/li&gt;
&lt;li&gt;The small balloon is hidden (&lt;code&gt;display: hidden&lt;/code&gt;) on smaller screens&lt;/li&gt;
&lt;li&gt;The background images are moved (&lt;code&gt;left&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt; property) to make a better composition for the new aspect ratio&lt;/li&gt;
&lt;li&gt;The bigger balloon is moved and also scaled down (&lt;code&gt;scale&lt;/code&gt; property) on smaller screens to better fit in the frame.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;9. Tips and Tricks
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Responsive font size
&lt;/h3&gt;

&lt;p&gt;For adjusting the font size you don't necessarily need to use Media Queries. you can achieve a responsive font size using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clamp"&gt;clamp()&lt;/a&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#selector&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;font-size&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1rem&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2.5vw&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2rem&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;It sets the font size to the middle value (2.5vw) while limiting (clamping) it between the start (1rem) and end (2rem) values. resulting in a font size that grows with screen width (vw) but is limited to a minimum and maximum size.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Dealing with the impossible
&lt;/h3&gt;

&lt;p&gt;Sometimes the positioning or other properties of an element are so different on different screen sizes that you just can't achieve it by adjusting Flex/Grid properties or moving it around using absolute positioning.&lt;/p&gt;

&lt;p&gt;In these situations, you can use two copies of the same element, position one perfectly for smaller screen sizes and one for the bigger ones. then hide one of them (&lt;code&gt;display: hidden;&lt;/code&gt;) and only show the one that is suitable for the current screen size using Media Queries (breakpoints).&lt;/p&gt;

&lt;p&gt;This is an example of this technique I used in &lt;a href="https://github.com/rashidshamloo/japan-slider"&gt;one of my projects&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/BVilewiGNDI"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Notice how the information text/element is in a different location and also included in the tilt on bigger screen sizes but changes position and is not tilted on smaller screens. this is achieved by using two different elements and showing one and hiding the other based on the screen size.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is a similar technique to what you would use for toggling the display of mobile menu on your website just applied to two similar elements with different positions / properties.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;10. Conclusion
&lt;/h2&gt;

&lt;p&gt;Responsive design and its implementation takes much more than just using Media Queries.&lt;/p&gt;

&lt;p&gt;You can show different image sizes or even totally different images, use the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/max-width"&gt;max-width&lt;/a&gt; property in addition to width, the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clamp"&gt;&lt;code&gt;clamp()&lt;/code&gt;&lt;/a&gt; function, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap"&gt;&lt;code&gt;flex-wrap&lt;/code&gt;&lt;/a&gt;, and more to customize your design for various screen sizes.&lt;/p&gt;

&lt;p&gt;It is also very easy to over-customize and use Media Queries when you don't need to, so you should always aim for the simplest solution because it'll be the most maintainable and won't break when a new device with a weird screen size enters the market.&lt;/p&gt;

</description>
      <category>css</category>
      <category>tutorial</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Introducing the react-next-parallax NPM package</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Tue, 05 Sep 2023 05:09:52 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/introducing-the-react-next-parallax-component-npm-package-emm</link>
      <guid>https://forem.com/rashidshamloo/introducing-the-react-next-parallax-component-npm-package-emm</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Q2vpbwj4CVo"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Table of Contents&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Introduction
&lt;/li&gt;
&lt;li&gt;2. The problem solved by react-next-parallax

&lt;ul&gt;
&lt;li&gt;1. Scale Problem
&lt;/li&gt;
&lt;li&gt;2. Containing elements within a 3D frame
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;3. What makes us think a scene is in the 3D space

&lt;ul&gt;
&lt;li&gt;1. Scale
&lt;/li&gt;
&lt;li&gt;2. Movement during rotation
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;4. Attributes

&lt;ul&gt;
&lt;li&gt;Scale&lt;/li&gt;
&lt;li&gt;Opacity&lt;/li&gt;
&lt;li&gt;Scale, Rotation, and Skew&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;5. Animation Modes
&lt;/li&gt;
&lt;li&gt;6. Animation Reverse
&lt;/li&gt;
&lt;li&gt;7. Multipliers
&lt;/li&gt;
&lt;li&gt;8. Animating elements that are being manipulated by the component
&lt;/li&gt;
&lt;li&gt;9. Multi-component setup
&lt;/li&gt;
&lt;li&gt;10. Improvements to react-next-tilt
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;1. Introduction
&lt;/h2&gt;

&lt;p&gt;After spending countless hours developing this component over the past month, experimenting with different approaches, testing and making sure that the component is implemented correctly, writing the documentation, and developing multiple demos to showcase how it works, I'm excited to announce the &lt;a href="https://www.npmjs.com/package/react-next-parallax"&gt;react-next-parallax&lt;/a&gt; component and the corresponding NPM package.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-next-parallax"&gt;react-next-parallax&lt;/a&gt; uses &lt;a href="https://www.npmjs.com/package/react-next-tilt"&gt;react-next-tilt&lt;/a&gt; (&lt;a href="https://dev.to/rashidshamloo/react-next-tilt-and-react-flip-tilt-npm-packages-24p0"&gt;introductory blog article&lt;/a&gt;) as the foundation and adds support for having a dynamic parallax scene in a confined frame. It also supports different animations like movement, opacity, scale, rotation, and skew based on the tilt angle. It is highly customizable, offering settings for different animation modes and speeds on top of all the other customizations offered by &lt;a href="https://www.npmjs.com/package/react-next-tilt"&gt;react-next-tilt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To learn more about the component, how to install and use it, and all the different props and settings, you can check the package readme on NPM.js:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-next-parallax"&gt;react-next-parallax package on NPM.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the old saying goes: "A live demo is better than a thousand words". To see the component in action, you can check any of the following demos:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo"&gt;Main Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes"&gt;Attributes Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/control-element"&gt;Control Element Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-parallax/?path=/docs/fliptilt-react-next-parallax--docs"&gt;Storybook&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the rest of this article, I will go over the development process in more detail.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;2. The problem solved by react-next-parallax
&lt;/h2&gt;

&lt;p&gt;You can set up a parallax tilt effect using only &lt;a href="https://www.npmjs.com/package/react-next-tilt"&gt;react-next-tilt&lt;/a&gt; (as you can see on its &lt;a href="https://rashidshamloo.github.io/react-next-tilt_demo/"&gt;demo page&lt;/a&gt;) by translating/moving the elements along the z-axis. but you will run into two main problems when setting up parallax scenes this way.&lt;/p&gt;

&lt;p&gt;Let's say we have a scene with many layers, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--bLFqRQSx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9iyw0pcj1xli9pouw237.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--bLFqRQSx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9iyw0pcj1xli9pouw237.jpg" alt="Multi Layered Scene" width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By translating/moving the elements along the z-axis (giving layers in the front higher &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateZ"&gt;&lt;code&gt;translateZ()&lt;/code&gt;&lt;/a&gt; values) we can achieve a parallax effect:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Yah4Its3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikd29ptau32u5423vhk1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Yah4Its3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ikd29ptau32u5423vhk1.jpg" alt="Scene overflowing the frame" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;but we have already run into the first problem and that is:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;1. Scale Problem
&lt;/h3&gt;

&lt;p&gt;When elements are translated along the z-axis and are closer to the viewer, they appear to be bigger. it may be fine in other situations, but when we have a scene like this, we don't want the scale of the elements to change because then we would have to adjust the size of each element by scaling it down to achieve the original composition.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;2. Containing elements within a 3D frame
&lt;/h3&gt;

&lt;p&gt;The biggest problem we run into is the fact that we can't hide the parts of the images that are outside the tilt. You may think we can use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/overflow"&gt;&lt;code&gt;overflow: hidden&lt;/code&gt;&lt;/a&gt; but as I've mentioned in another &lt;a href="https://dev.to/rashidshamloo/making-a-3d-parallax-effect-with-css-2kpp"&gt;post&lt;/a&gt;, using it will flatten the image and remove the parallax effect.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Technical note: You may be thinking that this is possible by putting the &lt;code&gt;preserve-3d&lt;/code&gt; elements inside a container and applying &lt;code&gt;overflow: hidden&lt;/code&gt; to it, but it's not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Putting the tilt inside a parent/container with &lt;code&gt;overflow: hidden&lt;/code&gt;:&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the parent does hide the content outside of it, and the 3D effect is preserved, the content is not confined to the tilt element but to the parent. meaning it overflows the tilt element but then is cut off by the parent's bounds which doesn't look good.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using an intermediary element with &lt;code&gt;overflow: hidden&lt;/code&gt; inside the tilt containing the 3D content inside&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This could look like it works if you were dealing with a static scene. because the elements look like they're in 3D space and they are, just not in the 3D space we want!&lt;/p&gt;

&lt;p&gt;When we put an &lt;code&gt;overflow: hidden&lt;/code&gt; element inside a &lt;code&gt;preserve-3d&lt;/code&gt; element, it breaks the 3D stack at that point. and when we have another &lt;code&gt;preserve-3d&lt;/code&gt; element inside of it, a new 3D stack is created. so what happens is that the elements inside of it are transformed in the 3D space but then get flattened. and the flattened result is put inside the parent's 3D space. so they don't move depending on the tilt angle. (imagine rotating a TV showing a 3D scene inside a room)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So, the question is: "How can we have &lt;code&gt;overflow: hidden&lt;/code&gt; and 3D effect at the same time?"&lt;/p&gt;

&lt;p&gt;In order to answer this question, we first need to know what 3D is in the first place.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;3. What makes us think a scene is in the 3D space
&lt;/h2&gt;

&lt;p&gt;We look at our screens which are flat 2D surfaces but can tell if what we're looking at is 3D or not. there are two main factors that help us distinguish 2D from 3D:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;1. Scale
&lt;/h3&gt;

&lt;p&gt;Elements that are closer to us appear bigger and vice versa, elements that are further away appear smaller. but we don't need this in our scene as mentioned before so we can ignore it.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;2. Movement during rotation
&lt;/h3&gt;

&lt;p&gt;Elements that are closer to us move more according to the rotation angle and elements that are further away move in the opposite direction. elements in between have less movement. (If you hold a pen with the tip facing you, when you rotate it from the middle, the tip will move in the rotation direction, the middle will not move and the back will move in the opposite direction. and the more the rotation angle, the higher the movement difference will be.)&lt;/p&gt;

&lt;p&gt;We can mimic this behavior by moving some elements in the rotation direction and some in the opposite direction. the elements in between will have less movement or no movement at all. the amount of movement will determine how close or far the elements are from us. (Note that since the container is rotated/tilted already, this is the additional movement on top of it)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I got this idea after checking &lt;a href="https://atroposjs.com/"&gt;Atropos&lt;/a&gt; and seeing that it uses &lt;code&gt;translate()&lt;/code&gt; to achieve a similar effect.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the main idea and the starting point for this component.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;4. Attributes
&lt;/h2&gt;

&lt;p&gt;I decided to use data attributes to implement the idea similar to how Atropos does it. I also tried to keep the value format similar but I've not checked how they are implemented in Atropos, so there could be differences.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Offset
&lt;/h3&gt;

&lt;p&gt;To implement this idea I've used an &lt;code&gt;offset&lt;/code&gt; attribute that can be assigned to each element we want to be moved according to the tilt angle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-parallax-offset=&lt;/span&gt;&lt;span class="s"&gt;"±number"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then calculate the amount of movement in the X/Y axis using this simple formula:&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="nx"&gt;translate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;tiltAngle&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="nx"&gt;tiltMaxAngle&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;offset&lt;/span&gt;
&lt;span class="cm"&gt;/*
 * Note:
 * tiltAngle is in the [-tiltMaxAngle - tiltMaxAngle] range.
 * translateX is calculated using rotation around the Y axis and vice versa.
 * We have to reverse/negate the angle around the X axis in the calculation.
 * We set the value as percent and because of the way translate() works, it'll be a percentage of the dimension of the element itself (width for translateX() and height for translateY())
 * This value is multiplied by the offsetMultiplier that is mentioned later.
*/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way elements with higher &lt;code&gt;offset&lt;/code&gt; values will move more at higher tilt angles and will appear to be in the front, and elements with a negative &lt;code&gt;offset&lt;/code&gt; will move in the opposite direction and will appear to be in the back. giving the illusion of being in 3D space.&lt;/p&gt;

&lt;p&gt;You can see this attribute in action in the &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes/offset"&gt;Offset Demo&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;a&gt;&lt;/a&gt;- Opacity
&lt;/h3&gt;

&lt;p&gt;I noticed that Atropos also has an &lt;a href="https://atroposjs.com/docs#control-elements-offsets"&gt;opacity attribute&lt;/a&gt; that can be used to animate the opacity of the element based on the tilt angle (&lt;code&gt;start&lt;/code&gt; opacity at center and &lt;code&gt;end&lt;/code&gt; opacity at max tilt angle) and I decided to implement the same functionality in my component as well.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-parallax-opacity=&lt;/span&gt;&lt;span class="s"&gt;"start;end"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the implementation, I used the same &lt;a href="https://dev.to/rashidshamloo/react-next-tilt-and-react-flip-tilt-npm-packages-24p0#the-line-glare-effect"&gt;mapping method&lt;/a&gt; I used in the development of &lt;a href="https://www.npmjs.com/package/react-next-tilt"&gt;react-next-tilt&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If we want to animate the opacity from one edge to the other (&lt;code&gt;tiltAngle/tiltMaxAngle = [-1 - 1]&lt;/code&gt;) from start to end (&lt;code&gt;[start - end]&lt;/code&gt;) we can use this mapping:&lt;/p&gt;

&lt;p&gt;Mapping &lt;code&gt;[-1 - 1]&lt;/code&gt; to &lt;code&gt;[start - end]&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;+ 1 = [0 - 2] =&amp;gt; / 2 = [0 - 1] =&amp;gt; * (end - start) = [0 - (end-start)] =&amp;gt; + start = [start - end]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And since we want to animate from the center to the edge, we can use &lt;code&gt;Math.abs(tiltAngle/tiltMaxAngle) = [0 - 1]&lt;/code&gt; instead and drop the first two steps:&lt;/p&gt;

&lt;p&gt;Mapping &lt;code&gt;[0 - 1]&lt;/code&gt; to &lt;code&gt;[start - end]&lt;/code&gt;:&lt;br&gt;
&lt;code&gt;* (end - start) = [0 - (end-start)] =&amp;gt; + start = [start - end]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can see this attribute in action in the &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes/opacity"&gt;Opacity Demo&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  - &lt;a&gt;&lt;/a&gt;Scale, Rotation, and Skew
&lt;/h3&gt;

&lt;p&gt;I also added attributes and animations based on tilt angle for Scale, Rotation, and Skew in a similar manner.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-parallax-scale=&lt;/span&gt;&lt;span class="s"&gt;"start;end"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-parallax-rotation=&lt;/span&gt;&lt;span class="s"&gt;"start;end"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;data-parallax-skew=&lt;/span&gt;&lt;span class="s"&gt;"start;end"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see these attributes in action here:&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes/scale"&gt;Scale Demo&lt;/a&gt; - &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes/rotation"&gt;Rotation Demo&lt;/a&gt; - &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes/skew"&gt;Skew Demo&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While implementing these attributes, I kept performance and usability in mind. while animating these attributes makes use of transform functions, my implementation doesn't replace the whole &lt;code&gt;transform&lt;/code&gt; property and only overwrites/replaces the required functions so you can use other transform functions at the same time as using the desired attribute. A list of what transform functions each attribute overwrites/replaces is available in the &lt;a href="https://www.npmjs.com/package/react-next-parallax#attributes"&gt;readme&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;5. Animation Modes
&lt;/h2&gt;

&lt;p&gt;Since I already figured out how to animate each attribute from edge to edge instead of center to edge, I decided to add this as an option/prop.&lt;/p&gt;

&lt;p&gt;I implemented separate modes/calculations for the &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt; axes as well as an option that will animate the value using both &lt;code&gt;X&lt;/code&gt; and &lt;code&gt;Y&lt;/code&gt; tilt angles (from top left to bottom right).&lt;/p&gt;

&lt;p&gt;In total there are 4 animation modes available:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'center-to-edge'&lt;/li&gt;
&lt;li&gt;'edge-to-edge-x'&lt;/li&gt;
&lt;li&gt;'edge-to-edge-y'&lt;/li&gt;
&lt;li&gt;'edge-to-edge-both';&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can see them in action in the &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes"&gt;Attributes Demo&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;6. Animation Reverse
&lt;/h2&gt;

&lt;p&gt;After implementing the different animation modes, I thought it could be useful to be able to animate each attribute in reverse.(instead of being the &lt;code&gt;start&lt;/code&gt; value at the center and &lt;code&gt;end&lt;/code&gt; at the max angle, being &lt;code&gt;end&lt;/code&gt; value at the center and &lt;code&gt;start&lt;/code&gt; at the max angle, or instead of animating from &lt;code&gt;start&lt;/code&gt; to &lt;code&gt;end&lt;/code&gt; when hovered from left to right, animating from &lt;code&gt;start&lt;/code&gt; to &lt;code&gt;end&lt;/code&gt; when hovered from right to left)&lt;/p&gt;

&lt;p&gt;I also decided to add fine-grained control over which attribute we want to reverse (because for example after setting up the offsets, we don't want to change it and want to only change other attributes).&lt;/p&gt;

&lt;p&gt;In total, animation reverse has 8 modes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;'all'&lt;/li&gt;
&lt;li&gt;'all-except-offset'&lt;/li&gt;
&lt;li&gt;'offset'&lt;/li&gt;
&lt;li&gt;'opacity'&lt;/li&gt;
&lt;li&gt;'scale'&lt;/li&gt;
&lt;li&gt;'rotation'&lt;/li&gt;
&lt;li&gt;'skew'&lt;/li&gt;
&lt;li&gt;'none'&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;7. Multipliers
&lt;/h2&gt;

&lt;p&gt;While making the demos and setting up the scenes I found myself changing the offset values manually a lot to get the effect and movement speed I wanted so I decided to add an &lt;code&gt;offsetMultiplier&lt;/code&gt; that allows for easy adjustment of all offset values. I later added a multiplier for all other attributes as well.&lt;/p&gt;

&lt;p&gt;You can see the &lt;code&gt;offsetMultiplier&lt;/code&gt; in action in the &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo/attributes"&gt;Attributes Demo&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;8. Animating elements that are being manipulated by the component
&lt;/h2&gt;

&lt;p&gt;In the &lt;a href="https://rashidshamloo.github.io/react-next-parallax_demo"&gt;main demo&lt;/a&gt; for the component, there are two balloons that I've animated using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes"&gt;CSS keyframe animations&lt;/a&gt; and &lt;code&gt;transform: translateX/Y()&lt;/code&gt; functions. However, one of them also has an offset attribute set so its &lt;code&gt;transform: translateX/Y()&lt;/code&gt; functions are also manipulated by the component at the same time.&lt;/p&gt;

&lt;p&gt;This caused the CSS animation to override/ignore the &lt;code&gt;transform: translate()&lt;/code&gt; set by the component and the element didn't move according to the tilt angle.&lt;/p&gt;

&lt;p&gt;I tried using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API"&gt;Web Animation API&lt;/a&gt; to animate the element instead of @keyframes but the result was the same. and animating using the &lt;code&gt;left&lt;/code&gt; and &lt;code&gt;top&lt;/code&gt; properties resulted in jittery/not smooth movement.&lt;/p&gt;

&lt;p&gt;I then remembered about the separate &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/translate"&gt;&lt;code&gt;translate&lt;/code&gt;&lt;/a&gt; property we can use instead of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate"&gt;&lt;code&gt;transform: translate()&lt;/code&gt;&lt;/a&gt; and after using it, both the CSS animation and the components &lt;code&gt;translate()&lt;/code&gt; manipulation worked at the same time without interfering with each other.&lt;/p&gt;

&lt;p&gt;Also another workaround I figured out while writing the documentation is putting the element inside a parent/container and animating it instead of the element itself while the element is being manipulated by the component.&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;9. Multi-component setup
&lt;/h2&gt;

&lt;p&gt;Atropos has a multi-component demo on its website and after seeing it, I figured I could achieve a similar result with my component, using the &lt;a href="https://rashidshamloo.github.io/react-next-tilt_demo/control-element"&gt;controlElement&lt;/a&gt; prop I developed for &lt;a href="https://www.npmjs.com/package/react-next-tilt"&gt;react-next-tilt&lt;/a&gt; from the start that allows the component to be manipulated by other elements. That element could be another component as well which means it's a matter of putting multiple components inside another component and setting their control Element to the parent component.&lt;/p&gt;

&lt;p&gt;After implementing it, I am really happy with the result. plus I can use all the other attributes I've added to rotate, scale, skew, etc. each of the contained components at the same time which results in really cool effects.&lt;/p&gt;

&lt;p&gt;Here is a preview of what it looks like:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/KC4wdwSSbNM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I plan to polish it more, add some presets for easy setup and use, and publish it as a separate component.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;10. Improvements to react-next-tilt
&lt;/h2&gt;

&lt;p&gt;In the process of developing this component, I needed some extra functionality that I first implemented in this component then ported back to &lt;a href="https://www.npmjs.com/package/react-next-tilt"&gt;react-next-tilt&lt;/a&gt; and added as core functionality which resulted in it gaining some new features including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Support for setting &lt;code&gt;TiltRef&lt;/code&gt;, &lt;code&gt;FlipTiltRef&lt;/code&gt;, and &lt;code&gt;ParallaxRef&lt;/code&gt; as &lt;code&gt;controlElement&lt;/code&gt; (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/bf5fb413c5b15addab5dc74d3d832272def9d52b"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;onReset()&lt;/code&gt; callback function (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/e9e01473a088a28eab0d0cae66090f92584873d2"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;preserve3dEnable&lt;/code&gt; prop (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/bf5fb413c5b15addab5dc74d3d832272def9d52b"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;shadowType&lt;/code&gt; prop (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/7b8ae1cd0b655685307ea1247185136d3ee51f76"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;'all'&lt;/code&gt; position for &lt;code&gt;spotGlarePosition&lt;/code&gt; prop (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/644e30620722a7045eccfac65fd5160d1d0db72c"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;spotGlareSizePercent&lt;/code&gt; prop (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/38891b3418d1666059c512c79994c69895a1a8dd"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;gyro&lt;/code&gt; argument for the &lt;code&gt;onTilt()&lt;/code&gt; callback function (&lt;a href="https://github.com/rashidshamloo/react-next-tilt/commit/f2cfbf699d274e012c55feb2db3d618074ef278c"&gt;commit&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;small&gt;Images used in this article and demos are by &lt;a href="https://www.vecteezy.com/members/klyaksun"&gt;Yuliya Pauliukevich&lt;/a&gt; on &lt;a href="https://www.vecteezy.com/"&gt;vecteezy.com&lt;/a&gt;&lt;/small&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>npm</category>
      <category>frontend</category>
    </item>
    <item>
      <title>Preventing the Layout Shift Caused by Scrollbars</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Wed, 09 Aug 2023 21:47:46 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/preventing-the-layout-shift-caused-by-scrollbars-2flp</link>
      <guid>https://forem.com/rashidshamloo/preventing-the-layout-shift-caused-by-scrollbars-2flp</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;When content overflows the page and the scrollbar shows up, the content is pushed/shifted to the left and vice versa, when the scrollbar disappears, the content is pushed/shifted to the right:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/6Gq3lhwX-oM"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;This annoying layout shift can be prevented in multiple ways. In this article, I will go over them one by one:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Always showing the scrollbars
&lt;/h2&gt;

&lt;p&gt;This is the easiest and ugliest solution.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;overflow-y&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;scroll&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. The &lt;code&gt;scrollbar-gutter&lt;/code&gt; property
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/scrollbar-gutter"&gt;&lt;code&gt;scrollbar-gutter&lt;/code&gt;&lt;/a&gt; property has been made for this exact purpose. setting it to &lt;code&gt;stable&lt;/code&gt; will preserve the space for the scrollbar and prevent the layout shift.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="py"&gt;scrollbar-gutter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;stable&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... it doesn't work in Safari and the scrollbar track will always be visible on your page which is not desirable.&lt;/p&gt;

&lt;h2&gt;
  
  
  *. A little note about &lt;code&gt;100vw&lt;/code&gt; and &lt;code&gt;100%&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Before continuing to the next points, it is necessary to understand the difference between &lt;code&gt;100vw&lt;/code&gt; and &lt;code&gt;100%&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100vw : Full width &lt;em&gt;&lt;strong&gt;including&lt;/strong&gt;&lt;/em&gt; the scrollbar.&lt;/li&gt;
&lt;li&gt;100% : Full width &lt;em&gt;&lt;strong&gt;excluding&lt;/strong&gt;&lt;/em&gt; the scrollbar.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  3. Shifting the content to the right
&lt;/h2&gt;

&lt;p&gt;When the scrollbar is not showing, &lt;code&gt;100vw&lt;/code&gt; and &lt;code&gt;100%&lt;/code&gt; are equal, and when the scrollbar is showing, the difference between them is equal to the width of the scrollbar.&lt;/p&gt;

&lt;p&gt;So if we shift the content to the right by the difference of &lt;code&gt;100vw&lt;/code&gt; and &lt;code&gt;100%&lt;/code&gt;, we can prevent the layout shift. To achieve it we can use &lt;code&gt;padding-left&lt;/code&gt; on the parent/container element:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;padding-left&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;calc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;100vw&lt;/span&gt; &lt;span class="n"&gt;-&lt;/span&gt; &lt;span class="m"&gt;100%&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;&lt;a href="https://stackoverflow.com/a/30293718/21092502"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Positioning inside a &lt;code&gt;100vw&lt;/code&gt; width parent
&lt;/h2&gt;

&lt;p&gt;Since scrollbars don't affect the &lt;code&gt;vw&lt;/code&gt; unit, we can fix the problem by setting the width of the parent/container in the &lt;code&gt;vw&lt;/code&gt; unit and centering/positioning our elements inside of it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100vw&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="c"&gt;/* elements inside won't be affected by scrollbars */&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;flex&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;align-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;justify-content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&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;&lt;a href="https://www.reddit.com/r/webdev/comments/svfsl3/comment/hxgmhft/"&gt;Source&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The result after applying the 4th method:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/M-01kbWzC7g"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Testing the Redux Store using Cypress in Next.js (TypeScript)</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Wed, 09 Aug 2023 02:52:18 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/testing-the-redux-store-using-cypress-in-nextjs-typescript-1k6o</link>
      <guid>https://forem.com/rashidshamloo/testing-the-redux-store-using-cypress-in-nextjs-typescript-1k6o</guid>
      <description>&lt;p&gt;This is a quick step-by-step guide for setting up Redux (Toolkit) testing using Cypress. I assume you already know how to install, set up, and use Redux (Toolkit) and Cypress separately.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Accessing the Redux Store
&lt;/h2&gt;

&lt;p&gt;You can't directly import and interact with your Redux store inside your test spec file. You first need to add it to the &lt;code&gt;window&lt;/code&gt; in your &lt;code&gt;store.ts&lt;/code&gt; file. You can do it in two ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  - Adding the &lt;code&gt;store&lt;/code&gt; to the &lt;code&gt;window&lt;/code&gt; itself
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;This is not recommended because it can cause conflicts.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Window&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;store&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;store&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;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="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;Cypress&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="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&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;h3&gt;
  
  
  - Adding the &lt;code&gt;store&lt;/code&gt; to &lt;code&gt;window.Cypress&lt;/code&gt;
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Recommended&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;CypressWithStore&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Cypress&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;store&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="nb"&gt;global&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Window&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;CypressWithStore&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;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="s1"&gt;undefined&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&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;Cypress&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="nx"&gt;Cypress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Dispatching Actions
&lt;/h2&gt;

&lt;p&gt;You can use &lt;code&gt;invoke('dispatch', action)&lt;/code&gt; to dispatch actions to the store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cypress&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="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;store&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="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dispatch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;SomeAction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Reading the State
&lt;/h2&gt;

&lt;p&gt;You can use &lt;code&gt;invoke('getState')&lt;/code&gt; to read the state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;cy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;window&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Cypress&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="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;store&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="nf"&gt;invoke&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;getState&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="nf"&gt;its&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;stateVariable&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="nf"&gt;should&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;assertion&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>testing</category>
      <category>redux</category>
      <category>typescript</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Using Styled-Components with Next.js v13 (TypeScript)</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Mon, 07 Aug 2023 01:57:22 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/using-styled-components-with-nextjs-v13-typescript-2l6m</link>
      <guid>https://forem.com/rashidshamloo/using-styled-components-with-nextjs-v13-typescript-2l6m</guid>
      <description>&lt;p&gt;Table of Contents&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. Install Next.js (with TypeScript)
&lt;/li&gt;
&lt;li&gt;2. Install the &lt;code&gt;vscode-styled-components&lt;/code&gt; plugin
&lt;/li&gt;
&lt;li&gt;3. Install the &lt;code&gt;styled-components&lt;/code&gt; package
&lt;/li&gt;
&lt;li&gt;4. Add SSR support
&lt;/li&gt;
&lt;li&gt;5. Add global styles
&lt;/li&gt;
&lt;li&gt;6. Add formatting to global styles
&lt;/li&gt;
&lt;li&gt;7. Add a theme
&lt;/li&gt;
&lt;li&gt;8. Add the &lt;code&gt;theme&lt;/code&gt; type
&lt;/li&gt;
&lt;li&gt;9. Move providers into a separate file (optional)
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recently started a Next.js v13 project with &lt;a href="https://www.styled-components.com" rel="noopener noreferrer"&gt;styled-components&lt;/a&gt; and had to jump through many hoops to have a working setup. In this article, I will go over the process step by step.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;1. Install Next.js (with TypeScript)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npx create-next-app@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;2. Install the &lt;code&gt;vscode-styled-components&lt;/code&gt; plugin
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn9xkcctl2zz2uqhm4c3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcn9xkcctl2zz2uqhm4c3.png" alt="vscode-styled-components plugin" width="699" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;3. Install the &lt;code&gt;styled-components&lt;/code&gt; package
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install styled-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;4. Add SSR support
&lt;/h2&gt;

&lt;p&gt;Next.js renders the components on the server and &lt;a href="https://en.wikipedia.org/wiki/Hydration_(web_development)" rel="noopener noreferrer"&gt;hydrates&lt;/a&gt; them (adds the interactive parts) on the client. when using &lt;code&gt;styled-components&lt;/code&gt; with Next.js, styles get applied on the client meaning the first render on the server will be without any styles and there will be a visible delay before the styles are applied.&lt;/p&gt;

&lt;p&gt;There are multiple ways to add SSR support to &lt;code&gt;styled-components&lt;/code&gt; with Next.js:&lt;/p&gt;

&lt;h3&gt;
  
  
  A. Enabling &lt;code&gt;styled-components&lt;/code&gt; in &lt;code&gt;next.config.mjs&lt;/code&gt;
&lt;/h3&gt;


&lt;p&gt;You just need to edit your &lt;code&gt;next.config.mjs&lt;/code&gt; file and add the following to it:&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;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;compiler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;styledComponents&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://nextjs.org/docs/architecture/nextjs-compiler#styled-components" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  B. Global style registry
&lt;/h3&gt;

&lt;p&gt;Next.js suggests implementing a &lt;a href="https://nextjs.org/docs/app/building-your-application/styling/css-in-js#styled-components" rel="noopener noreferrer"&gt;global style registry component&lt;/a&gt; that collects all the styles and applies them to the &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;lib/registry.tsx&lt;/code&gt; file and add the following to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&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;useServerInsertedHTML&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="s1"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&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;ServerStyleSheet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;StyleSheetManager&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="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&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;StyledComponentsRegistry&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Only create stylesheet once with lazy initial state&lt;/span&gt;
  &lt;span class="c1"&gt;// x-ref: https://reactjs.org/docs/hooks-reference.html#lazy-initial-state&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;styledComponentsStyleSheet&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ServerStyleSheet&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

  &lt;span class="nf"&gt;useServerInsertedHTML&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;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styledComponentsStyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getStyleElement&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;styledComponentsStyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;clearTag&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;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styles&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;/&lt;/span&gt;&lt;span class="err"&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="s1"&gt;undefined&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="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;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;StyleSheetManager&lt;/span&gt; &lt;span class="nx"&gt;sheet&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;styledComponentsStyleSheet&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StyleSheetManager&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;ul&gt;
&lt;li&gt;In your root &lt;code&gt;layout.tsx&lt;/code&gt; file import &lt;code&gt;StyledComponentsRegistry&lt;/code&gt; and wrap &lt;code&gt;children&lt;/code&gt; in it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;StyledComponentsRegistry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/registry&lt;/span&gt;&lt;span class="dl"&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;RootLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&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;body&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;StyledComponentsRegistry&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StyledComponentsRegistry&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;/body&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;/html&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;h3&gt;
  
  
  C. The &lt;code&gt;styled-components&lt;/code&gt; Babel plugin
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;styled-components&lt;/code&gt; provides a &lt;a href="https://styled-components.com/docs/tooling#babel-plugin" rel="noopener noreferrer"&gt;Babel plugin&lt;/a&gt; you can use for adding &lt;a href="https://nextjs.org/learn/foundations/how-nextjs-works/rendering" rel="noopener noreferrer"&gt;SSR&lt;/a&gt; support. To use it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install it using the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D babel-plugin-styled-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;.babelrc&lt;/code&gt; file in the root of your project and add the following to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "presets": ["next/babel"],
  "plugins": ["babel-plugin-styled-components"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, Next.js will automatically use &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; instead of &lt;a href="https://swc.rs/" rel="noopener noreferrer"&gt;SWC&lt;/a&gt; to compile your code since a custom configuration is present.&lt;/p&gt;

&lt;p&gt;However, there are cases where this might not work, for example &lt;a href="https://nextjs.org/docs/pages/building-your-application/optimizing/fonts" rel="noopener noreferrer"&gt;&lt;code&gt;next/font&lt;/code&gt;&lt;/a&gt; requires SWC and you will get this error message if you're using it alongside the custom &lt;code&gt;.babelrc&lt;/code&gt; configuration file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Syntax error: "next/font" requires SWC although Babel is being used
due to a custom babel config being present.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  D. The &lt;code&gt;styled-components&lt;/code&gt; SWC plugin
&lt;/h3&gt;

&lt;p&gt;You can also use the &lt;code&gt;styled-components&lt;/code&gt; &lt;a href="https://www.npmjs.com/package/@swc/plugin-styled-components" rel="noopener noreferrer"&gt;SWC plugin&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install it using the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i -D @swc/plugin-styled-components
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;.swcrc&lt;/code&gt; file in the root of your project and add the following to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "jsc": {
    "experimental": {
      "plugins": [
        [
          "@swc/plugin-styled-components",
          {
            "ssr": true
          }
        ]
      ]
    }
  }
}

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;5. Add global styles
&lt;/h2&gt;

&lt;p&gt;Global styles is the place to add your fonts, CSS reset/normalize, and any other style you want applied globally.&lt;/p&gt;

&lt;p&gt;You can achieve this using the &lt;a href="https://styled-components.com/docs/api#createglobalstyle" rel="noopener noreferrer"&gt;&lt;code&gt;createGlobalStyle()&lt;/code&gt;&lt;/a&gt; function:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;styles/GlobalStyles.ts&lt;/code&gt; file and add to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;createGlobalStyle&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="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&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;GlobalStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
  // your global styles
`&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="nx"&gt;GlobalStyles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In your root &lt;code&gt;layout.tsx&lt;/code&gt; file, import and add the &lt;code&gt;GlobalStyles&lt;/code&gt; component:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;StyledComponentsRegistry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/registry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/GlobalStyles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&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;body&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;StyledComponentsRegistry&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;GlobalStyles&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StyledComponentsRegistry&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;/body&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;/html&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;6. Add formatting to global styles
&lt;/h2&gt;

&lt;p&gt;While writing your global styles you may have noticed that formatting doesn't work for it even though it works for other styled components. to fix the issue you can do one of the following in your &lt;code&gt;styles/GlobalStyles.ts&lt;/code&gt; file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using the &lt;code&gt;css&lt;/code&gt; helper function:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;createGlobalStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;css&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="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;css&lt;/span&gt;&lt;span class="s2"&gt;`
  // your global styles
`&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;GlobalStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
  &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;styles&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/prettier/prettier/pull/9025#issuecomment-678655928" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Using an intermediate object:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;createGlobalStyle&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="s1"&gt;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&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;GlobalStyles&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
  // your global styles
`&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="nx"&gt;GlobalStyles&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/prettier/prettier/issues/11196#issuecomment-951878725" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;7. Add a theme
&lt;/h2&gt;

&lt;p&gt;You may have colors, font sizes, or other global variables that you need to access in multiple components. you can use a &lt;a href="https://styled-components.com/docs/advanced#theming" rel="noopener noreferrer"&gt;theme&lt;/a&gt; to do it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;styles/theme.ts&lt;/code&gt; file and add your colors to it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;colorName1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#aabbcc&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;colorName2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hsla(50, 60%, 70%, 0.5)&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="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="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In your root &lt;code&gt;layout.tsx&lt;/code&gt; file, import your &lt;code&gt;theme&lt;/code&gt; as well as &lt;code&gt;ThemeProvider&lt;/code&gt; and wrap &lt;code&gt;children&lt;/code&gt; in it:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;StyledComponentsRegistry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./lib/registry&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;GlobalStyles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/GlobalStyles&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;ThemeProvider&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="s1"&gt;styled-components&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;theme&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&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;body&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;StyledComponentsRegistry&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;GlobalStyles&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;ThemeProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ThemeProvider&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;/StyledComponentsRegistry&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;/body&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;/html&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;ul&gt;
&lt;li&gt;Access the &lt;code&gt;theme&lt;/code&gt; in your components:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;styled&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="s1"&gt;styled-components&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;MyDiv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  background-color: &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;colorName1&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;8. Add the &lt;code&gt;theme&lt;/code&gt; type
&lt;/h2&gt;

&lt;p&gt;You may have noticed when using the &lt;code&gt;theme&lt;/code&gt; in your components, you are not getting any IntelliSense/auto-complete with TypeScript. To fix it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;types/styled.d.ts&lt;/code&gt; file and add the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styled-components&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;theme&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="s1"&gt;../styles/theme&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;styled-components&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;DefaultTheme&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;Theme&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;&lt;a href="https://stackoverflow.com/a/72071824" rel="noopener noreferrer"&gt;Source&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now you have auto-complete with your theme:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4g1yrcgw4mcsvnteqhif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4g1yrcgw4mcsvnteqhif.png" alt="Styed-components theme auto-complete" width="528" height="135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a&gt;&lt;/a&gt;9. Move providers into a separate file (optional)
&lt;/h2&gt;

&lt;p&gt;If you don't like having &lt;code&gt;'use client'&lt;/code&gt; in your &lt;code&gt;layout.tsx&lt;/code&gt; file, and when you have multiple providers as we do now, you can move all of your providers to a &lt;code&gt;Providers.tsx&lt;/code&gt; file and import and use it in your &lt;code&gt;layout.tsx&lt;/code&gt; file instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create the &lt;code&gt;Providers.tsx&lt;/code&gt; file and add the following:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&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;StyledComponentsRegistry&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/registry&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;ThemeProvider&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="s1"&gt;styled-components&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;theme&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/theme&lt;/span&gt;&lt;span class="dl"&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;Providers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&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;StyledComponentsRegistry&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;ThemeProvider&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; 
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ThemeProvider&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;/StyledComponentsRegistry&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Providers&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Edit your &lt;code&gt;layout.tsx&lt;/code&gt; file to look like this:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Providers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Providers&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;GlobalStyles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/GlobalStyles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;RootLayout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PropsWithChildren&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;html&lt;/span&gt; &lt;span class="nx"&gt;lang&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&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;body&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;Providers&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;GlobalStyles&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;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/Providers&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;/body&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;/html&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;🎉 Congratulations! Now you can finally start making your styled-components with Next.js v13!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>"react-next-tilt" and "react-flip-tilt" NPM Packages</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Wed, 02 Aug 2023 07:32:22 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/react-next-tilt-and-react-flip-tilt-npm-packages-24p0</link>
      <guid>https://forem.com/rashidshamloo/react-next-tilt-and-react-flip-tilt-npm-packages-24p0</guid>
      <description>&lt;p&gt;Table of Contents&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1. The Beginning
&lt;/li&gt;
&lt;li&gt;2. The Line Glare Effect
&lt;/li&gt;
&lt;li&gt;3. useImperativeHandle() and Async Animation
&lt;/li&gt;
&lt;li&gt;4. Problems with the Tilt Component
&lt;/li&gt;
&lt;li&gt;5. Reinventing a Better Wheel (Tilt Component)
&lt;/li&gt;
&lt;li&gt;6. The Spot Glare Effect
&lt;/li&gt;
&lt;li&gt;7. requestAnimationFrame() and will-change Property
&lt;/li&gt;
&lt;li&gt;8. Testing
&lt;/li&gt;
&lt;li&gt;9. Storybook
&lt;/li&gt;
&lt;li&gt;10. Flip-Back Direction
&lt;/li&gt;
&lt;li&gt;11. Control Element
&lt;/li&gt;
&lt;li&gt;12. JSDoc Descriptions
&lt;/li&gt;
&lt;li&gt;13. The Final Note
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This will be a long post in which I go over why and how I made these components/packages.&lt;/p&gt;

&lt;p&gt;tl;dr: I spent a lot of time on them and learned a lot in the process. Have fun using them :)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. &lt;a&gt;&lt;/a&gt;The Beginning
&lt;/h2&gt;

&lt;p&gt;The past few months have been a fun ride for me for sure. After doing many coding challenges on &lt;a href="https://www.frontendmentor.io/profile/rashidshamloo" rel="noopener noreferrer"&gt;frontendmentor.io&lt;/a&gt;, I started working on my portfolio website in Next.js. I began implementing the features I always wanted to work on in my portfolio, like Next.js App directory, i18n (Internationalization), react-hook-form, email.js, and many cool CSS/3D/Animation ideas I've had for a while that you'll see once it's finished.&lt;/p&gt;

&lt;p&gt;While working on my portfolio, I came across a website (&lt;a href="https://evolany.com/" rel="noopener noreferrer"&gt;https://evolany.com/&lt;/a&gt;) which I found inspiring for its sleek design and interactive elements. What they use for the members section is an image that flips and turns into a tilt element on hover. I thought to myself: "That looks cool, I should be able to do that in React."&lt;/p&gt;

&lt;p&gt;At this point, I was already using a tilt component (&lt;a href="https://www.npmjs.com/package/react-parallax-tilt" rel="noopener noreferrer"&gt;react-parallax-tilt&lt;/a&gt;) in my portfolio, and after checking &lt;a href="https://www.w3schools.com/howto/howto_css_flip_card.asp" rel="noopener noreferrer"&gt;this page&lt;/a&gt; I had the general idea of how it should be done, a container with &lt;code&gt;transform-style: preserve-3d&lt;/code&gt;, with two children, one tilt and the other an image, both having &lt;code&gt;backface-visibility: hidden&lt;/code&gt; and the tilt being rotated to face backward at the start. For the animation, I decided to use &lt;a href="https://www.npmjs.com/package/framer-motion" rel="noopener noreferrer"&gt;&lt;code&gt;framer-motion&lt;/code&gt;&lt;/a&gt; because I was already familiar with it and knew it had what was needed to get the job done (and I'm glad I did because later I needed to &lt;code&gt;await&lt;/code&gt; the animation and it was easy with &lt;code&gt;framer-motion&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;So I started making the component and after some trouble as usual (has anything worked well the first few times, ever?!), like &lt;a href="https://www.framer.com/motion/motionvalue/" rel="noopener noreferrer"&gt;&lt;code&gt;motionValue&lt;/code&gt;&lt;/a&gt; having the &lt;code&gt;NaN&lt;/code&gt; value sometimes and breaking everything when the animation type was &lt;code&gt;spring&lt;/code&gt; and there was a set &lt;code&gt;duration&lt;/code&gt; (which to fix, I needed to remove &lt;code&gt;duration&lt;/code&gt; and use &lt;code&gt;mass&lt;/code&gt; and &lt;code&gt;stiffness&lt;/code&gt; instead to control the duration), I managed to make a working component that flipped on hover and showed the tilt component.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a&gt;&lt;/a&gt;The Line Glare Effect
&lt;/h2&gt;

&lt;p&gt;One of the features of the element on the mentioned site is the line glare that shows when the tilt element is at a certain angle to give the impression of light hitting it which gives it a nice 3D feel, but the tilt component I was using (and any other ones that I checked) lacked this feature. so I decided to make the effect myself and inject it into the tilt component I was using. At first, I used &lt;a href="https://react.dev/reference/react-dom/createPortal" rel="noopener noreferrer"&gt;&lt;code&gt;createPortal()&lt;/code&gt;&lt;/a&gt; to do this but later switched to the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild" rel="noopener noreferrer"&gt;&lt;code&gt;appendChild()&lt;/code&gt;&lt;/a&gt; method.&lt;/p&gt;

&lt;p&gt;To get the movement of the line glare right, I checked to see how the original element worked. The original element is made using vanilla JavaScript and CSS. The animation is done using CSS with the JavaScript code updating the CSS variables. While the code is very clean and admirable, it wasn't of much use to me since I was doing things differently. nevertheless, I looked at how the movement was done and tried to do a similar thing in my component as well. after playing around with the numbers for a while, I could get something that almost worked but I didn't really get the math behind it. At this point, I was spending a lot of time fiddling with the numbers but not getting the exact effect, and even if I did, I couldn't improve it further by adding customizations like different directions, movement, etc. so I decided to ignore the original implementation and come up with my own idea/logic instead. After thinking about it for a while, I came up with a way to do it and now I knew exactly what I was doing, and not only did it help me solve this problem but it was crucial in making other parts and customizations of the component as well.&lt;/p&gt;

&lt;p&gt;Here, I would like to do a small rant about the advice floating around that is: "You just need to code enough to get something working right now and not think about the future". Had I not figured out my own way of doing things and settled on something that just worked for now, I wouldn't have been able to complete the other parts of this project nor gain the knowledge I now have. I believe it's better to deeply understand the problem and the solution and learn something from it rather than just hacking it to work for now.&lt;/p&gt;

&lt;p&gt;Anyway, back to the topic, the line glare element is twice the size of the main element and placed on top of it with only the part inside visible. It will move only left or right depending on the sum of &lt;code&gt;offsetX&lt;/code&gt; and &lt;code&gt;offsetY&lt;/code&gt; (&lt;code&gt;offsetX/Y&lt;/code&gt; is a number between 0 and 1 depending on the distance of the pointer/touch from the edge of the element) but since it's a diagonal line, it gives the impression of it going from top to bottom as well.&lt;br&gt;
Because the line glare element is twice the size and translate is relative to the size of the line glare element, not the main element, at first it has &lt;code&gt;translateX&lt;/code&gt; of -100% so it is placed outside the component, and at &lt;code&gt;translateX&lt;/code&gt; of 50% it will exit the main element from the right side:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/xenodochial-burnell-pymntl"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The line glare should be visible only when the component is tilted so when the pointer is at the center (&lt;code&gt;offsetX&lt;/code&gt;(0.5) + &lt;code&gt;offsetY&lt;/code&gt;(0.5) = 1) it should be outside the main element. Let's say we want the line glare to be visible while the component is being tilted to the top left corner (&lt;code&gt;offsetX&lt;/code&gt;(0) + &lt;code&gt;offsetY&lt;/code&gt;(0)=0), then we need to map the &lt;code&gt;offsetX + offsetY&lt;/code&gt; ([1 - 0]) to the line glare element position/translateX or [-100% - 50%]:&lt;/p&gt;

&lt;p&gt;To map [1 - 0] to [-100 - 50], we can do:&lt;br&gt;
&lt;code&gt;* -1 = [-1 - 0] -&amp;gt; * 3/2 = [-1.5 - 0] -&amp;gt; + 0.5 = [-1 - 0.5] -&amp;gt; * 100 = [-100 - 50]&lt;/code&gt;&lt;br&gt;
or &lt;br&gt;
&lt;code&gt;((offsetX + offsetY) * (-3 / 2) + 0.5) * 100&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Even though it took me a day or two to come up with this method, after that, everything made sense and I also implemented customizations like reverse movement, different line angle, width, color, etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. &lt;a&gt;&lt;/a&gt;useImperativeHandle() and Async Animation
&lt;/h2&gt;

&lt;p&gt;At this point, I had a working component and I really liked the flip-tilt effect, so I decided to make it into an NPM package so others can use it as well. for that, I needed to make a demo page to showcase the component and how it worked. the best way to showcase it was by having multiple components side by side, similar to how the original element was presented, but I also wanted to add customization selection elements to showcase the power of React and that while it may take longer to make the component at first, after that, you can easily integrate as many of it as you want into your application with different props/customizations.&lt;/p&gt;

&lt;p&gt;While making the demo page and working on the component, I thought it'd be cool if I could showcase the components on the demo page by animating them in a pattern/sequence to showcase the flip animation. I tried flipping the component programmatically by changing its &lt;code&gt;flipped&lt;/code&gt; state. and while the component did flip, changing the component's state re-rendered it, meaning the animation got interrupted (not to mention the performance impact of having to constantly re-render a lot of components while doing animations). I needed a way to run the flip animation inside of my component without re-rendering it.&lt;/p&gt;

&lt;p&gt;After doing some research I came across the &lt;a href="https://react.dev/reference/react/useImperativeHandle" rel="noopener noreferrer"&gt;&lt;code&gt;useImperativeHandle()&lt;/code&gt;&lt;/a&gt; hook. It lets you customize the ref handle of your component and expose internal properties/functions to the outside so a parent component can call a child function without having to re-render it. This was exactly what I was looking for and after learning and using it, I could achieve the animation effect I wanted without re-rendering. It also allowed me to expose more needed functions at the later stages of development.&lt;/p&gt;

&lt;p&gt;I also exported the current flipped state of the component (&lt;code&gt;isFlipped()&lt;/code&gt;) using the same method (I use a &lt;a href="https://react.dev/learn/referencing-values-with-refs" rel="noopener noreferrer"&gt;&lt;code&gt;ref&lt;/code&gt;&lt;/a&gt; to keep track of the flipped state instead of &lt;a href="https://react.dev/learn/state-a-components-memory" rel="noopener noreferrer"&gt;&lt;code&gt;state&lt;/code&gt;&lt;/a&gt; to minimize re-rendering, and it took a while to figure out that I needed to use a getter function to export its value).&lt;/p&gt;

&lt;p&gt;After testing the &lt;code&gt;isFlipped()&lt;/code&gt; state and &lt;code&gt;flip()&lt;/code&gt; function, I came across a new problem. After running the following code:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;I expected the component to flip and then flip back but nothing happened on the screen. this was because the functions ran instantly without waiting for the previous one to finish. to fix the problem I needed to make the animation and the &lt;code&gt;flip()&lt;/code&gt; function &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Asynchronous" rel="noopener noreferrer"&gt;asynchronous&lt;/a&gt; so they could be &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/await" rel="noopener noreferrer"&gt;&lt;code&gt;await&lt;/code&gt;&lt;/a&gt;ed. Thankfully, the only thing I needed to do to convert my &lt;code&gt;flip()&lt;/code&gt; function to an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function" rel="noopener noreferrer"&gt;async function&lt;/a&gt; was adding the &lt;code&gt;await&lt;/code&gt; keyword to my &lt;code&gt;framer-motion&lt;/code&gt; &lt;a href="https://www.framer.com/motion/animate-function/###then" rel="noopener noreferrer"&gt;&lt;code&gt;animate()&lt;/code&gt;&lt;/a&gt; call. after that, I could &lt;code&gt;await&lt;/code&gt; the &lt;code&gt;flip()&lt;/code&gt; function and the result was the expected animation:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flip&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;


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

&lt;/div&gt;
&lt;h2&gt;
  
  
  4. &lt;a&gt;&lt;/a&gt;Problems with the Tilt Component
&lt;/h2&gt;

&lt;p&gt;While refactoring and polishing the component and playing around with it more, I noticed some problems with the tilt component I was using, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After the flip animation, the tilt component was always straight (not tilted) while I wanted it to be tilted at the start depending on the pointer position. to fix it, I tried:

&lt;ul&gt;
&lt;li&gt;Calculating the rotation angle myself in my component based on pointer position and setting the transform rotation of the tilt  element. which didn't work because the transform got overridden by the tilt component.&lt;/li&gt;
&lt;li&gt;Dispatching &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/mousemove_event" rel="noopener noreferrer"&gt;&lt;code&gt;mouseMove&lt;/code&gt;&lt;/a&gt; events to the tilt element after running the flip animation which kind of worked and the tilt component appeared tilted after the flip animation. but I didn't like this method as it was too hacky and the multiple random events it dispatched could interfere with the final application that was going to use my component.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;It's possible to set the start tilt angle using &lt;code&gt;initialAngleX/Y&lt;/code&gt; props, but then it changes the rest/reset position as well and re-renders the component, and using the &lt;code&gt;tiltAngleX/YManual&lt;/code&gt; props disables the tilt on hover.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Changing some of the props didn't immediately take effect and I had to set them as the component &lt;code&gt;key&lt;/code&gt; to force an update. (&lt;a href="https://codesandbox.io/p/sandbox/white-fast-dl3n9d" rel="noopener noreferrer"&gt;example&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The tilt component I was using (and all the other ones I checked), attaches the event handlers to the element that is being tilted itself, so after tilting, the element goes out of the cursor position and resets back, and then comes under the cursor and so on. this caused jittery movement around the edges:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/850813938" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Again at this point, I felt like I was spending too much time trying to make something work that even if it did, I would've been limited by its features and functionality and I wouldn't have been able to fully customize it. So even though I was halfway through writing the readme for the package before publishing it, after giving it some thought, I decided to scrap it all and start over and make my own tilt component from scratch.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. &lt;a&gt;&lt;/a&gt;Reinventing a Better Wheel (Tilt Component)
&lt;/h2&gt;

&lt;p&gt;I separated all the logic related to the tilt component into another project and started making my own tilt component. I already knew how to calculate the tilt angle from the offset from before when I was trying to set the start angle of the previous tilt component, I just needed to write all the other parts and customizations...&lt;/p&gt;

&lt;p&gt;After coming this far, I wanted to make the best component I can with my current skills and also learn in the process so I didn't want to skimp on anything.&lt;/p&gt;

&lt;p&gt;I finished the tilt logic, added touch and gyroscope support, scale, reverse, reset, initial angle, and many more customizations and exported the needed functions and properties using the &lt;code&gt;useimperative()&lt;/code&gt; hook, all the while trying to minimize component re-renders by using refs, &lt;a href="https://react.dev/reference/react/useMemo" rel="noopener noreferrer"&gt;&lt;code&gt;useMemo()&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://react.dev/reference/react/useCallback" rel="noopener noreferrer"&gt;&lt;code&gt;useCallback()&lt;/code&gt;&lt;/a&gt;, and keeping performance in mind overall.&lt;/p&gt;

&lt;p&gt;Also from my experience with the previous tilt component in my portfolio, there was an annoyance in mobile/touch that when trying to tilt the component, the page scrolled at the same time. I addressed that and added a "disable scroll on touch" option as well.&lt;/p&gt;

&lt;p&gt;While the time I spent before may have seemed like lost time, the knowledge I gained doing all that, helped me greatly in making the tilt component and the customizations.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. &lt;a&gt;&lt;/a&gt;The Spot Glare Effect
&lt;/h2&gt;

&lt;p&gt;To implement the spot glare effect, I used an element twice the size of the main element with a radial gradient background which is placed so that its center is at the corner of the main element and depending on the pointer/touch position moves to the other corner giving the impression of light hitting the element at different angles:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/wispy-water-mtg6xl"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;For the movement and customizations, I used the same mapping method that I used for the line glare effect. (&lt;code&gt;offsetX&lt;/code&gt;([0 - 1]) to &lt;code&gt;translateX&lt;/code&gt;([0% - 50%]))&lt;/p&gt;

&lt;h2&gt;
  
  
  7. &lt;a&gt;&lt;/a&gt;requestAnimationFrame() and will-change Property
&lt;/h2&gt;

&lt;p&gt;Most of the other tilt components seem to be based on &lt;a href="https://gijsroge.github.io/tilt.js/" rel="noopener noreferrer"&gt;&lt;code&gt;tilt.js&lt;/code&gt;&lt;/a&gt;. while taking a look at it, I noticed that it boasts about being "requestAnimationFrame powered". this piqued my interest and I started looking at what it is and how to implement it in my component.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame" rel="noopener noreferrer"&gt;&lt;code&gt;requestAnimationFrame()&lt;/code&gt;&lt;/a&gt; takes a function as the argument and tells the browser to run that function before the &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/Repaint" rel="noopener noreferrer"&gt;repaint&lt;/a&gt; phase. this results in faster/smoother animations than animating the element using JavaScript alone, and can reach to almost the same speed as the native CSS animations.&lt;/p&gt;

&lt;p&gt;Once I knew how it worked, I implemented it in my component by putting the parts of my code that updated the animation/transform in the &lt;code&gt;requestAnimationFrame()&lt;/code&gt; function. at first, I tried batching all the animation updates in one call, but later decided against it as it meant if there was going to be a frame drop because the calculations couldn't be made before the next frame, the frame drop would affect all the tilt, line, and glare elements. by separating it into different calls for each element, if one of them lagged a frame, the others would still render which results in smoother animations overall. (of course, this could not work in another case in which the animations are in a sequence or depend on each other)&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/will-change" rel="noopener noreferrer"&gt;&lt;code&gt;will-change&lt;/code&gt;&lt;/a&gt; CSS property is another performance optimization used by other components. it lets the browser know which properties are about to be changed so it can be prepared for it which usually means not cleaning up the memory as fast as it can and and holding on to it. this can cause higher memory usage if you just randomly apply it to your elements.&lt;/p&gt;

&lt;p&gt;The proper way to use the &lt;code&gt;will-change&lt;/code&gt; property is to set it before starting your animation (changing the &lt;code&gt;transform&lt;/code&gt; in this case) and remove it after you are done. The way I implemented it in my component is that when the pointer/touch enters the component, I add the property to the tilt and glare elements and when the pointer/touch leaves it, I remove it. this lets the browser know that while the pointer/touch is inside the component, it should expect changes to the transform property.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. &lt;a&gt;&lt;/a&gt;Testing
&lt;/h2&gt;

&lt;p&gt;After more refactoring, I was writing my new readme files for the now two packages that I had made, but even though I had tested the functionality by manually changing different props and playing around with it, I've not had written any tests for the components yet. And after coming so far, I didn't want to publish an NPM package without proper tests and just say: "Trust me, it works!".&lt;/p&gt;

&lt;p&gt;I knew &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; from before when I learned it to write the tests for my previous NPM packages. but at this point even though it was on my "to learn" list, I didn't know how to write tests for React components.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React testing Library&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The most popular library for testing React components is the &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt; and I started learning it. because I was using &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite.js&lt;/a&gt; for development, I had to set up and use &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt; instead of Jest which I did without much trouble since Vitest is made on top of Jest and has a similar syntax.&lt;/p&gt;

&lt;p&gt;After learning how to write the tests, &lt;a href="https://testing-library.com/docs/dom-testing-library/api-events" rel="noopener noreferrer"&gt;fire events&lt;/a&gt;, and things like the &lt;a href="https://testing-library.com/docs/user-event/intro/" rel="noopener noreferrer"&gt;difference between FireEvent and UserEvent&lt;/a&gt; and setting everything up, I started writing my first test in React Testing Library.&lt;/p&gt;

&lt;p&gt;I spent some time before adjusting the CSS style of the component to make the internal elements respect the width/height set as props so I decided to write the first test for the &lt;code&gt;width&lt;/code&gt; property to see if the component actually rendered at the given width when provided with a bigger-size image as child.&lt;/p&gt;

&lt;p&gt;And you guessed it, I ran into yet another problem. the returned computed width (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect" rel="noopener noreferrer"&gt;getBoundingClientRect().width&lt;/a&gt;) was an empty string. At first, I thought something was wrong with the component but after investigating further, I figured out the reason.&lt;/p&gt;

&lt;p&gt;React testing library uses &lt;a href="https://www.npmjs.com/package/jsdom" rel="noopener noreferrer"&gt;jsdom&lt;/a&gt; (or others like &lt;a href="https://www.npmjs.com/package/happy-dom" rel="noopener noreferrer"&gt;happy-dom&lt;/a&gt;) under the hood to emulate the browser environment and enable testing of different properties. but it doesn't render the component in an actual browser meaning the styles can't be computed and the returned computed style is just an object with the correct keys but empty strings as values.&lt;/p&gt;

&lt;p&gt;This would've been fine if it was only limited to the width/height props but I was using computed styles (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect" rel="noopener noreferrer"&gt;getBoundingClientRect()&lt;/a&gt;) inside my component to calculate the offsets and all the positions/movements which meant it broke everything.&lt;/p&gt;

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

&lt;p&gt;The solution was to use a testing method that actually rendered the component in a browser so I had access to the computed styles. two of the most used testing libraries for this purpose are &lt;a href="https://www.cypress.io/" rel="noopener noreferrer"&gt;Cypress&lt;/a&gt; and &lt;a href="https://www.selenium.dev/" rel="noopener noreferrer"&gt;Selenium&lt;/a&gt;. I decided on Cypress (while reading on Reddit that they both suck and we should use &lt;a href="https://playwright.dev/" rel="noopener noreferrer"&gt;playwright&lt;/a&gt; instead...) and started learning it.&lt;/p&gt;

&lt;p&gt;Cypress has a jQuery-like syntax (actually incorporates jQuery itself) and uses &lt;a href="https://www.chaijs.com/" rel="noopener noreferrer"&gt;Chai&lt;/a&gt; (not Jest/Vitest) for assertions. it also has its own implementation of promises that can't be used with async/await...&lt;/p&gt;

&lt;p&gt;Another interesting thing about Cypress is that it's &lt;a href="https://docs.cypress.io/guides/core-concepts/introduction-to-cypress#When-Elements-Are-Missing" rel="noopener noreferrer"&gt;asynchronous&lt;/a&gt;, meaning when you say "expect an element to have a certain style property" it doesn't just check it there and then. it waits (by default 4 seconds) for the element to have/attain that style and if the condition passes within the timeout, the test passes. this is especially useful for testing things like &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API" rel="noopener noreferrer"&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/a&gt;ing a resource that could take a variable amount of time to complete.&lt;/p&gt;

&lt;p&gt;To my surprise, learning and writing the tests in Cypress went rather smoothly, probably because I was already familiar with React Testing Library and Jest/Vitest. I only touched the component testing part of Cypress though and look forward to writing integration/e2e tests using it for my future applications.&lt;/p&gt;

&lt;p&gt;The only problem I had with Cypress was that when testing for the tilt angle after &lt;a href="https://docs.cypress.io/api/commands/trigger" rel="noopener noreferrer"&gt;triggering&lt;/a&gt; the event at certain positions like &lt;a href="https://docs.cypress.io/api/commands/trigger#Arguments" rel="noopener noreferrer"&gt;&lt;code&gt;"topRight"&lt;/code&gt;&lt;/a&gt;, the component's tilt angle was short of what it needed to be. at first, I thought it was a problem with my rotation calculation and implemented some workarounds like rounding the numbers and it fixed the problem but left a bad taste in my mouth because I wasn't sure what the root cause of the problem was. After revisiting my calculations later on, I came to the conclusion that my math was correct and there was no reason for rounding so I undid it and investigated further. it turned out that the position Cypress triggered the event at, was off by "1px" and it was causing the problem. so I provided my own correct trigger positions instead of relying on the built-in positions and it fixed everything.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://player.vimeo.com/video/850814878" width="710" height="399"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Overall, even though setting up and running the tests took some time (mainly because I was learning at the same time), it let me catch some bugs that I missed and also helped test the new features and changes later on.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. &lt;a&gt;&lt;/a&gt;Storybook
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://storybook.js.org/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt; was another tool/library on my "to learn" list. It provides an environment where you can render your component in different states and with different props (a story) and preview, test, or play around with it. it's also good for showcasing/documenting different features of a component and the effect of changing individual props on how the component looks and behaves.&lt;/p&gt;

&lt;p&gt;I started learning it by watching a youtube video but when it came to using it, I noticed that in the new version, the syntax was changed and most of what I learned was useless... still it was well documented and after reading the docs I got the hang of it. I enjoyed using it and it is something I plan to use in the future as well.&lt;/p&gt;

&lt;p&gt;The only thing that took some time was figuring out how to do the customizations I wanted to make, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hiding the actions I didn't want/need&lt;/li&gt;
&lt;li&gt;Changing the input type shown for each prop&lt;/li&gt;
&lt;li&gt;Showing only a few selected props for a selected story&lt;/li&gt;
&lt;li&gt;Showing/Hiding a prop in the prop table&lt;/li&gt;
&lt;li&gt;Setting the component window background to a dark color by default&lt;/li&gt;
&lt;li&gt;Setting the whole page's background to a dark background by default&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, I implemented all the customizations I wanted to make. &lt;/p&gt;

&lt;p&gt;You can check it out here: &lt;a href="https://rashidshamloo.github.io/react-next-tilt/" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  10. &lt;a&gt;&lt;/a&gt;Flip-Back Direction
&lt;/h2&gt;

&lt;p&gt;I set up the flip animation in a way that allowed the flip direction to be changed by passing a prop (&lt;code&gt;flipDirection&lt;/code&gt;). Depending on the prop's value I set the rest/initial rotation to either 180 or -180 degrees and rotated to 0 on hover/touch. (the reason for it being this way not the other way around is that I wanted the tilt (back) element to be at 0 rotation when being interacted with so the tilt angle and glare movements would work the proper way and not in reverse). and when the pointer/touch left the component the rotation was set back to it's initial rotation. meaning it flipped from one side and flipped back to that side as well. (the original element the idea came from works in this way as well)&lt;/p&gt;

&lt;p&gt;This wasn't easy to notice when using a flat image and was best seen when using a 3d/parallax element. so I set up a demo page with parallax elements to showcase this feature and just when I was almost done with it, it occurred to me: "Wouldn't it be cool if I could implement a 360-degree continues rotation so if the flip animation starts from one side, it ends by going to the other side instead of back to where it started?"&lt;/p&gt;

&lt;p&gt;The challenge I faced when implementing this feature was that for a 360 degree rotation, the element's rotation needed to start at 180° and go to 0° and then to -180°, but when it animated again, the rotation was at -180° not 180°. so when rotating to 0° again, it started animating from the wrong side.&lt;/p&gt;

&lt;p&gt;To fix the problem I needed to negate the rotation value after the element finished animating so if it was -180°, it needed to be switched back to 180°. but changing the rotation caused the element to do a whole unwanted animation from -180° to 180°. I needed a way to just change the rotation value without actually animating the element.&lt;/p&gt;

&lt;p&gt;After a little bit of tinkering, I could achieve this using &lt;code&gt;framer-motion&lt;/code&gt; motionValue's &lt;a href="https://www.framer.com/motion/motionvalue/###jump" rel="noopener noreferrer"&gt;&lt;code&gt;jump()&lt;/code&gt;&lt;/a&gt; function. After doing the needed adjustments to the flip function to get it to work properly, I was really happy with the end result and added the &lt;code&gt;flipBackDirection&lt;/code&gt; property to the component and set the 360° rotation as the default.&lt;/p&gt;

&lt;p&gt;You can check it out here: &lt;a href="https://rashidshamloo.github.io/react-flip-tilt_demo/parallax" rel="noopener noreferrer"&gt;Parallax Demo&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  11. &lt;a&gt;&lt;/a&gt;Control Element
&lt;/h2&gt;

&lt;p&gt;Another idea I came up with during later stages of development was adding the ability to attach the component's event handlers to other elements and let them control it. this allowed for some cool effects to be implemented as well as opened the door to adding the full-page listening option to the element (since the page/document is just another element that the event handlers should be attached to). It also let me learn more about the difference between &lt;a href="https://react.dev/reference/react-dom/components/common#react-event-object" rel="noopener noreferrer"&gt;Synthetic Events&lt;/a&gt; and Native Events and how they worked.&lt;/p&gt;

&lt;p&gt;I implemented this feature for both the react-next-tilt and react-flip-tilt components while allowing for customizations and also accepting refs as well as elements as input. And of course, added the &lt;code&gt;fullPageListening&lt;/code&gt; option too. Making the demo pages took a while, but I'm really happy with the end result.&lt;/p&gt;

&lt;p&gt;You can check the control element demo here:&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-tilt_demo/control-element" rel="noopener noreferrer"&gt;react-next-tilt&lt;/a&gt; - &lt;a href="https://rashidshamloo.github.io/react-flip-tilt_demo/control-element" rel="noopener noreferrer"&gt;react-flip-tilt&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  12. &lt;a&gt;&lt;/a&gt;JSDoc Descriptions
&lt;/h2&gt;

&lt;p&gt;I was already familiar with &lt;a href="https://jsdoc.app/" rel="noopener noreferrer"&gt;JSDoc&lt;/a&gt; from writing prop descriptions for my previous NPM packages, but I decided to go all in and provide more/better descriptions. I added the following information for the props of both components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Description of the prop&lt;/li&gt;
&lt;li&gt;Note (any extra information)&lt;/li&gt;
&lt;li&gt;Default value&lt;/li&gt;
&lt;li&gt;Example&lt;/li&gt;
&lt;li&gt;Link to a relevant source for more information which can be a  demo page, storybook page, or a website like &lt;a href="https://developer.mozilla.org/" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Parameter information for functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets developers know everything there is to know about the prop from inside their IDE by just hovering over it:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zhzjf02oo7ph77omlmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9zhzjf02oo7ph77omlmn.png" alt="JSDoc Prop Description"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  13. &lt;a&gt;&lt;/a&gt;The Final Note
&lt;/h2&gt;

&lt;p&gt;Even though I spent a lot of time and ran into many problems while making these components/packages, and most likely because of that, I learned many new things and solidified my knowledge on what I already knew which were my main goals when I started this project.&lt;/p&gt;

&lt;p&gt;If you're interested in trying these packages, you can find them here:&lt;/p&gt;
&lt;h4&gt;
  
  
  Tilt ("react-next-tilt")
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-next-tilt" rel="noopener noreferrer"&gt;NPM.js&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-tilt_demo" rel="noopener noreferrer"&gt;Main Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-tilt_demo/control-element" rel="noopener noreferrer"&gt;Control Element Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-next-tilt/?path=/docs/tilt-react-next-tilt--docs" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rashidshamloo/react-next-tilt" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;
  
  
  FlipTilt ("react-flip-tilt")
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/react-flip-tilt" rel="noopener noreferrer"&gt;NPM.js&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-flip-tilt_demo" rel="noopener noreferrer"&gt;Main Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-flip-tilt_demo/parallax" rel="noopener noreferrer"&gt;Parallax Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-flip-tilt_demo/control-element" rel="noopener noreferrer"&gt;Control Element Demo&lt;/a&gt;&lt;br&gt;
&lt;a href="https://rashidshamloo.github.io/react-flip-tilt/?path=/docs/fliptilt-react-flip-tilt--docs" rel="noopener noreferrer"&gt;Storybook&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/rashidshamloo/react-flip-tilt" rel="noopener noreferrer"&gt;GitHub Repository&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/kJNmUW2Ag9c"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;Hopefully, you've learned something new by reading this article and knowing about the problems I've encountered. However, the best way to learn is to run into the problems yourself and solve them after putting some time and thought, only then will the knowledge stick in your mind. So I suggest pursuing the next wild idea you have and trying to implement it. even if you don't finish it or no one uses it, you will learn invaluable lessons along the way.&lt;/p&gt;

&lt;p&gt;Next, I will focus on finishing my portfolio before I get distracted again...&lt;/p&gt;

&lt;p&gt;P.S. I skipped over many parts in this article like designing and making the demo pages mobile friendly, making the images used in the demo pages, &lt;a href="https://dev.to/rashidshamloo/styling-input-range-sliders-nge"&gt;customizing the sliders&lt;/a&gt; for the tilt demo page, adding a11y to the demo pages, etc.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Making a 3D Parallax Effect with CSS</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Thu, 27 Jul 2023 17:32:26 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/making-a-3d-parallax-effect-with-css-2kpp</link>
      <guid>https://forem.com/rashidshamloo/making-a-3d-parallax-effect-with-css-2kpp</guid>
      <description>&lt;p&gt;While it may seem complicated at first, making a 3D parallax effect with CSS is pretty easy and straightforward.&lt;/p&gt;

&lt;p&gt;Let's say we have a &lt;code&gt;div&lt;/code&gt; element with two nested &lt;code&gt;div&lt;/code&gt; elements (children) and we want to apply the 3D parallax effect to them:&lt;/p&gt;

&lt;h3&gt;
  
  
  - HTML
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"container"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"child1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"child2"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  - CSS
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;150px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;green&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;display&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;place-items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;animation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rotate&lt;/span&gt; &lt;span class="m"&gt;5s&lt;/span&gt; &lt;span class="n"&gt;ease-in-out&lt;/span&gt; &lt;span class="n"&gt;infinite&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#child1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;70%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&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="nf"&gt;#child2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30%&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background-color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="py"&gt;grid-area&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After applying a simple CSS &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/@keyframes"&gt;@keyframes&lt;/a&gt; animation for demonstration purposes, it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/affectionate-panini-np4yxh"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;you can add the 3D parallax effect by following these steps:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Add &lt;code&gt;transform-style: preserve-3d&lt;/code&gt; to the parent/container
&lt;/h2&gt;

&lt;p&gt;For the 3D effect to work, you first need to set the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-style"&gt;&lt;code&gt;transform-style: preserve-3d&lt;/code&gt;&lt;/a&gt; on the parent/container element. This will let the browser know that it should render the element and it's children in 3D space.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;transform-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;preserve-3d&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Add the &lt;code&gt;perspective&lt;/code&gt; property to the parent/container (optional)
&lt;/h2&gt;

&lt;p&gt;The next step is adding the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/perspective"&gt;&lt;code&gt;perspective&lt;/code&gt;&lt;/a&gt; property to the parent/container element. the value of this property determines how close/far the elements are from the user. you can set the value using 'px', 'em', 'rem', etc. units.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;perspective&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Move/Translate the children along the &lt;code&gt;Z&lt;/code&gt; axis
&lt;/h2&gt;

&lt;p&gt;Even though the elements are now rendered in 3D space, all of the elements are on the same plane ( they all have &lt;code&gt;translateZ&lt;/code&gt; of &lt;code&gt;0&lt;/code&gt; which means they are stacked on top of each other). to really see the 3D effect you need to move them back and forth along the &lt;code&gt;Z&lt;/code&gt; axis. you can do it in different ways:&lt;/p&gt;

&lt;h3&gt;
  
  
  - The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/translate"&gt;&lt;code&gt;translate&lt;/code&gt;&lt;/a&gt; property
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;translate: 0 0 100px;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  - The&lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translateZ"&gt;&lt;code&gt;translateZ()&lt;/code&gt;&lt;/a&gt; function of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform"&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/a&gt; property
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transform: translateZ(100px);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  - The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/translate3d"&gt;&lt;code&gt;translate3d&lt;/code&gt;&lt;/a&gt; function of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform"&gt;&lt;code&gt;transform&lt;/code&gt;&lt;/a&gt; property
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transform: translate3d(0, 0, 100px);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;After following these steps, our CSS will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nf"&gt;#container&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="nl"&gt;transform-style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;preserve-3d&lt;/span&gt;
  &lt;span class="n"&gt;perspective&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1000px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#child1&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="py"&gt;translate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;50px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;#child2&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;...&lt;/span&gt;
  &lt;span class="py"&gt;translateZ&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is what it looks like in action:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/zen-babbage-zstyz7"&gt;
&lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;While the 3D parallax effect is easy to set up, there are a few caveats.&lt;/p&gt;

&lt;p&gt;When applying some CSS properties, the browser has to flatten the layers (remove the 3D effect), which means if you use these properties, the effect will not work. these properties include:&lt;/p&gt;

&lt;h3&gt;
  
  
  - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/overflow"&gt;&lt;code&gt;overflow&lt;/code&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode"&gt;&lt;code&gt;mix-blend-mode&lt;/code&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/opacity"&gt;&lt;code&gt;opacity&lt;/code&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/filter"&gt;&lt;code&gt;filter&lt;/code&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;h3&gt;
  
  
  - &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/clip-path"&gt;&lt;code&gt;clip-path&lt;/code&gt;&lt;/a&gt;
&lt;/h3&gt;

&lt;p&gt;To read more about these properties and possible workarounds, you can read &lt;a href="https://css-tricks.com/things-watch-working-css-3d/#aa-things-that-break-3d-or-cause-flattening"&gt;this article&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Exporting Declaration Files in Vite.js</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Wed, 26 Jul 2023 03:56:46 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/exporting-declaration-files-in-vitejs-f6m</link>
      <guid>https://forem.com/rashidshamloo/exporting-declaration-files-in-vitejs-f6m</guid>
      <description>&lt;p&gt;JavaScript is not a statically typed language. TypeScript gives you the illusion that there are types during development but once it's compiled into JavaScript, all that disappears. that's why you need libraries like &lt;a href="https://zod.dev/" rel="noopener noreferrer"&gt;Zod&lt;/a&gt; for runtime type checking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qgxb6rb66zixh6mm9k0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5qgxb6rb66zixh6mm9k0.jpg" alt="TypeScript is Fake"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you want to share the library/package you've written in TypeScript with others, you need to generate and include a separate type declaration file (ending in &lt;code&gt;.d.ts&lt;/code&gt;) so other developers can access your type definitions during development. (You also need to add a &lt;code&gt;"types"&lt;/code&gt; entry in &lt;code&gt;"package.json"&lt;/code&gt; pointing to that file)&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Limitations of &lt;code&gt;tsconfig.json&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;In the &lt;code&gt;tsconfig.json&lt;/code&gt; file that is generated after running the &lt;code&gt;tsc --init&lt;/code&gt; command (it comes by default in many libraries like Vite.js), there are options you can enable to generate declaration files like &lt;code&gt;"declaration"&lt;/code&gt;, &lt;code&gt;"declarationDir"&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;But you will run into limitations and problems if you just use the options available in this file, like:&lt;/p&gt;

&lt;h3&gt;
  
  
  - Not being able to generate declaration files for only specific files
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;"include"&lt;/code&gt; option is for including the files in your whole project not just type declaration generation. so if you exclude other files (set it to only the files you need declarations for), those files won't be seen by typescript at all and you will get lots of errors.&lt;/p&gt;

&lt;h3&gt;
  
  
  - Not being able to rename/modify the generated declaration files
&lt;/h3&gt;

&lt;p&gt;When your project grows, you may want to separate your type definitions into another file like &lt;code&gt;types/types.ts&lt;/code&gt; and import it in your main file. but when building/shipping, you want all of your types to be in a &lt;code&gt;index.d.ts&lt;/code&gt; file in the root of your &lt;code&gt;dist&lt;/code&gt; folder. you can't achieve that with &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. &lt;a href="https://www.npmjs.com/package/vite-plugin-dts" rel="noopener noreferrer"&gt;vite-plugin-dts&lt;/a&gt; to the rescue
&lt;/h2&gt;

&lt;p&gt;There is a plugin called &lt;a href="https://www.npmjs.com/package/vite-plugin-dts" rel="noopener noreferrer"&gt;&lt;code&gt;vite-plugin-dts&lt;/code&gt;&lt;/a&gt; for Vite.js which makes generating declaration files much easier.&lt;/p&gt;

&lt;h3&gt;
  
  
  - Installation
&lt;/h3&gt;

&lt;p&gt;You can install it by running this command:&lt;/p&gt;

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

npm i vite-plugin-dts -D


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

&lt;/div&gt;

&lt;p&gt;Then in your &lt;code&gt;vite.config.ts&lt;/code&gt; file add these lines:&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dts&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vite-plugin-dts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// add dts() to the plugins array&lt;/span&gt;
&lt;span class="nl"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;dts&lt;/span&gt;&lt;span class="p"&gt;()],&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  - Generating declarations for specific files
&lt;/h3&gt;

&lt;p&gt;By default, declaration files will be generated for all files but you can limit it to specific files by using the &lt;code&gt;include&lt;/code&gt; option:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;dts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path/to/file.ts&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  - Renaming/Modifying the generated declaration files
&lt;/h3&gt;

&lt;p&gt;You can rename the generated files to something else or even modify the content by using the &lt;code&gt;beforeWriteFile&lt;/code&gt; option. you can pass a function that takes two arguments &lt;code&gt;(filePath: string, content: string)&lt;/code&gt; and returns an object with the same-name properties &lt;code&gt;{filepath: 'new/path/to/file.d.ts', content: 'newContent'}&lt;/code&gt;. if you return &lt;code&gt;false&lt;/code&gt; the file will be skipped.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;dts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;beforeWriteFile&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;filePath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path/to/file.d.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;index.d.ts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;}),&lt;/span&gt;


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

&lt;/div&gt;
&lt;h3&gt;
  
  
  - Changing the output directory
&lt;/h3&gt;

&lt;p&gt;you can use the &lt;code&gt;outDir&lt;/code&gt; option to limit declaration file generation to specific directories. (you can achieve this using the options in &lt;code&gt;tsconfig.json&lt;/code&gt; as well)&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;

&lt;span class="nf"&gt;dts&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;outDir&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dist&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;There are many more options available that you can check in the &lt;a href="https://www.npmjs.com/package/vite-plugin-dts#options" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;The build process in JavaScript/TypeScript can be confusing with all of the different tools and options available. hopefully, this article can help with making it a little easier.&lt;/p&gt;

</description>
      <category>vite</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Styling Input Range Sliders</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Thu, 06 Jul 2023 02:26:09 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/styling-input-range-sliders-nge</link>
      <guid>https://forem.com/rashidshamloo/styling-input-range-sliders-nge</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6vt2ekl800iitbwdbqw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6vt2ekl800iitbwdbqw.jpg" alt="Input range slider meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Styling &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/range" rel="noopener noreferrer"&gt;input range sliders&lt;/a&gt; might seem easy at first but there are a lot of caveats and it's more complicated than it seems. in this article, I will go through what is needed to have working, styled horizontal and vertical input range sliders.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The Shadow DOM
&lt;/h2&gt;

&lt;p&gt;When you add the &lt;code&gt;&amp;lt;input type="range" /&amp;gt;&lt;/code&gt; line to your HTML, under the hood, browsers add multiple additional DOM elements to actually render it on the page. this implementation differs for each browser and is something you need to keep in mind when styling different parts of the slider.&lt;br&gt;
These DOM elements are hidden by default and are called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_components/Using_shadow_DOM" rel="noopener noreferrer"&gt;shadow DOM elements&lt;/a&gt; for that reason. the first step is to actually see what the structure of these elements looks like.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. Revealing the Shadow DOM
&lt;/h2&gt;

&lt;p&gt;To see the shadow DOM elements, you need to change some settings in your browser's DevTools.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;Open the DevTools (F12)&lt;/li&gt;
&lt;li&gt;Click the &lt;code&gt;gear&lt;/code&gt; icon at the top right corner&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;Preferences&lt;/code&gt; tab, under the &lt;code&gt;Elements&lt;/code&gt; section, enable the &lt;code&gt;Show user agent shadow DOM&lt;/code&gt; option&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;ol&gt;
&lt;li&gt;In the address bar type &lt;code&gt;about:config&lt;/code&gt;, hit Enter, and click &lt;code&gt;Accept the Risk and Continue&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;devtools.inspector.showAllAnonymousContent&lt;/code&gt; and set it to &lt;code&gt;true&lt;/code&gt; &lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;

&lt;p&gt;After doing the steps above you can check your &lt;code&gt;&amp;lt;input type="range" /&amp;gt;&lt;/code&gt; element in the DevTools and see what is actually rendered:&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7zvp1jl1jrm4n8rrag4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe7zvp1jl1jrm4n8rrag4.png" alt="Input range slider shadow DOM in Chrome"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwmsgfr4cza4ns5xtw2h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbwmsgfr4cza4ns5xtw2h.png" alt="Input range slider shadow DOM in Firefox"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Pseudo-Elements
&lt;/h2&gt;

&lt;p&gt;Each browser allows us to target these shadow elements using different pseudo-elements/selectors:&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Track: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-slider-runnable-track" rel="noopener noreferrer"&gt;&lt;code&gt;::-webkit-slider-runnable-track&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Thumb: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::-webkit-slider-thumb" rel="noopener noreferrer"&gt;&lt;code&gt;::-webkit-slider-thumb&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Track: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-range-track" rel="noopener noreferrer"&gt;&lt;code&gt;::-moz-range-track&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Thumb: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-range-thumb" rel="noopener noreferrer"&gt;&lt;code&gt;::-moz-range-thumb&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Progress: &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/::-moz-range-progress" rel="noopener noreferrer"&gt;&lt;code&gt;::-moz-range-progress&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  4. Styling
&lt;/h2&gt;

&lt;p&gt;Now that we know the structure of the shadow elements and how to target them using pseudo-elements/selectors, we can start styling them. but before doing that, we need to remove the default style (appearance) applied by the browser. we can do it using the &lt;code&gt;appearance&lt;/code&gt; CSS property:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;appearance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;none&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;We can also set the background to transparent to get rid of the default background color:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;

&lt;span class="nt"&gt;background-color&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;transparent&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


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

&lt;/div&gt;
&lt;p&gt;Now we can apply our custom styles using the pseudo-elements/selectors.&lt;br&gt;
A simple style (using flashy colors for demonstration purposes) would look like this:&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/xenodochial-khayyam-6mt6nz"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;As you can see both from the shadow DOM elements and the pseudo-elements/selectors, Chrome does not provide a &lt;code&gt;progress&lt;/code&gt; element for us to style. but we can achieve a similar result by doing one of the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;CSS&lt;/p&gt;

&lt;p&gt;We can cast a shadow from the &lt;code&gt;thumb&lt;/code&gt; to the start of the &lt;code&gt;track&lt;/code&gt; and clip it to give the impression of it being the same height as the track. (&lt;a href="https://codepen.io/ShadowShahriar/pen/zYPPYrQ" rel="noopener noreferrer"&gt;example&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;JavaScript&lt;/p&gt;

&lt;p&gt;We can get the position of the &lt;code&gt;thumb&lt;/code&gt; and set the background of the &lt;code&gt;track&lt;/code&gt; to be a &lt;code&gt;linear-gradient&lt;/code&gt; that's one color up to that position and another to the end. (&lt;a href="https://codepen.io/duplich/pen/qjYQEZ" rel="noopener noreferrer"&gt;example&lt;/a&gt;)&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ We can also use &lt;code&gt;:hover&lt;/code&gt;, &lt;code&gt;:active&lt;/code&gt;, and &lt;code&gt;:disabled&lt;/code&gt; selectors to further customize the appearance in different states.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. Vertical Slider
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Edit: After playing around with it a bit more, I've figured out the problem. I was using &lt;code&gt;rotate : -90deg;&lt;/code&gt; to rotate the horizontal slider and make a vertical one. using the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/rotate" rel="noopener noreferrer"&gt;&lt;code&gt;rotate&lt;/code&gt;&lt;/a&gt; property seems to glitch the slider movement somehow. if we use &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/rotate" rel="noopener noreferrer"&gt;&lt;code&gt;transform: rotate(-90deg);&lt;/code&gt;&lt;/a&gt; instead, everything works fine and it won't get stuck. so just do that and ignore the next two sections ^^;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f2jebecwgn7l4j97s5a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1f2jebecwgn7l4j97s5a.jpg" alt="Vertical slider meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we rotate our horizontal slider to make a vertical one, it will look and work fine on desktop but on mobile/touch it won't work properly and will be stuck. to address this issue, each browser provides an extra property we can use to tell it to render a vertical slider instead of a horizontal one:&lt;/p&gt;

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

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

&lt;span class="nt"&gt;-webkit-appearance&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;slider-vertical&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;


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

&lt;/div&gt;

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

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

&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"range"&lt;/span&gt; &lt;span class="na"&gt;orient=&lt;/span&gt;&lt;span class="s"&gt;"vertical"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;But there's a problem. before, we set the &lt;code&gt;appearance&lt;/code&gt; to &lt;code&gt;none&lt;/code&gt; to get rid of the default styles but setting these properties will override our styles and revert the slider to how it looked like before.&lt;/p&gt;

&lt;p&gt;To work around this, what I came up with is rotating our styled slider to make a vertical but non-functional slider. then we put a working vertical slider made using the properties above, on top of it, hide it, and when its value changes, we update our original slider. so what users interact with will be the default vertical slider but what they see is our styled slider. (we only need to do this for mobile/touch)&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/input-range-slider-forked-h4hrzg"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ Still on Firefox sometimes the vertical slider gets stuck on mobile/touch.&lt;/p&gt;

&lt;p&gt;ℹ️ We also need to add &lt;code&gt;writing-mode: bt-lr;&lt;/code&gt; for older versions of Edge.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  6. orient="vertical" in React/TypeScript
&lt;/h2&gt;

&lt;p&gt;After adding &lt;code&gt;orient="vertical"&lt;/code&gt; to the &lt;code&gt;input&lt;/code&gt; tag in React/TypeScript, we will get this error:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;Property 'orient' does not exist on type 'DetailedHTMLProps&amp;lt;InputHTMLAttributes&amp;lt;HTMLInputElement&amp;gt;, HTMLInputElement&amp;gt;'&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;According to React, the &lt;code&gt;orient&lt;/code&gt; property does not exist on the &lt;code&gt;input&lt;/code&gt; tag, so we have to add the property ourselves. we can use &lt;code&gt;module declare&lt;/code&gt; to do this. we can either add the following lines to the top of the current file or place it in a &lt;code&gt;index.d.ts&lt;/code&gt; file:&lt;/p&gt;

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

&lt;span class="kr"&gt;declare&lt;/span&gt; &lt;span class="kr"&gt;module&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;InputHTMLAttributes&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;orient&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&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;blockquote&gt;
&lt;p&gt;ℹ️ You can use this method to add any custom property to any HTML tag you want.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;🎉 Congratulations! Now, you have probably given up on customizing the input range slider and have decided to either use the default browser style or a component library!&lt;/p&gt;

&lt;p&gt;Whether you're brave enough to do it or decided against it, hopefully, you've learned something from reading this article that could help you in the future. :)&lt;/p&gt;




&lt;p&gt;P.S.&lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Styling for Safari, Edge, Opera, Brave, etc. would be similar to Chrome since they either use &lt;a href="https://webkit.org/" rel="noopener noreferrer"&gt;Webkit&lt;/a&gt; or are compatible with it. &lt;/li&gt;
&lt;li&gt;I've ignored Internet Explorer throughout this article but it has its own set of pseudo-elements you need to style separately.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Testing device orientation (gyroscope) on localhost using Vite</title>
      <dc:creator>Rashid Shamloo</dc:creator>
      <pubDate>Wed, 28 Jun 2023 14:05:54 +0000</pubDate>
      <link>https://forem.com/rashidshamloo/how-to-test-device-orientation-gyroscope-on-localhost-using-vite-16bf</link>
      <guid>https://forem.com/rashidshamloo/how-to-test-device-orientation-gyroscope-on-localhost-using-vite-16bf</guid>
      <description>&lt;p&gt;I'm making a tilt component atm and wanted to make it respond to gyroscope (device orientation) changes. there were some caveats with testing it locally so I decided to write this post to explain it.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Device Orientation Event
&lt;/h2&gt;

&lt;p&gt;To detect device orientation (gyroscope) changes, you need to add an event listener for the &lt;code&gt;deviceorientation&lt;/code&gt; event. this is how it's done in React using TypeScript:&lt;/p&gt;

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

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleDeviceOrientation&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;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;DeviceOrientationEvent&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;// do something with `e.alpha`, `e.beta`, and `e.gamma`&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="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="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="s1"&gt;deviceorientation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;handleDeviceOrientation&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="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="s1"&gt;deviceorientation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;handleDeviceOrientation&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;handleDeviceOrientation&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We can then get the rotation values in degrees around each axis from the event object:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;e.alpha&lt;/em&gt; : rotation around the Z axis&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;e.beta&lt;/em&gt; : rotation around the X axis&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;e.gamma&lt;/em&gt; : rotation around the Y axis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Testing in Chrome
&lt;/h2&gt;

&lt;p&gt;To test device orientation in Chrome, you can use the &lt;code&gt;Sensors&lt;/code&gt; tab in Chrome Devtools. to access it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;F12&lt;/code&gt; to open DevTools &lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Three dots&lt;/code&gt;-&amp;gt;&lt;code&gt;More Tools&lt;/code&gt;-&amp;gt;&lt;code&gt;Sensors&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;In the &lt;code&gt;Orientation&lt;/code&gt; section, you can drag/rotate the 3d phone model around to change the device orientation and see the effect in your application:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6irv238ikvki0f89wx8e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6irv238ikvki0f89wx8e.png" alt="Device Orientation in Google Chrome"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Testing on your phone
&lt;/h2&gt;

&lt;p&gt;Now you probably want to test your application on your phone to see how it actually works. First, you need to make your dev server accessible to your local network. To do that, run the dev server with the &lt;code&gt;-- --host&lt;/code&gt; flag. (no, it's not a typo!)&lt;/p&gt;

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

npm run dev -- --host


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

&lt;/div&gt;

&lt;p&gt;Now your dev server is exposed to your local network and it should list the IP addresses/ports it's listening to, like:&lt;/p&gt;

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

➜  Local:   http://localhost:5173/
➜  Network: http://192.168.1.x:5173/


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

&lt;/div&gt;

&lt;p&gt;Make sure your phone is connected to the same network as your PC and open the listed address/port. it should connect and show your application. (I usually do this to test all my applications on my phone in addition to Chrome's responsive view mode)&lt;br&gt;
Now, you will notice that the device orientation event doesn't work on your phone!&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Vite dev server with HTTPS
&lt;/h2&gt;

&lt;p&gt;Your phone doesn't give access to the device orientation (gyroscope) sensor when your app is served under the &lt;code&gt;HTTP&lt;/code&gt; protocol. It &lt;em&gt;has&lt;/em&gt; to be served under &lt;code&gt;HTTPS&lt;/code&gt; for it to work!&lt;br&gt;
To run your dev server in HTTPS, do these steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install the &lt;code&gt;@vitejs/plugin-basic-ssl&lt;/code&gt; package:
```
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;npm i @vitejs/plugin-basic-ssl&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2. Edit your `vite.config.ts` file to reflect these changes:
```ts


import basicSsl from '@vitejs/plugin-basic-ssl'
plugins: [basicSsl()] // add basicSsl() to the plugins array


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

&lt;/div&gt;

&lt;p&gt;If you're using React, your &lt;code&gt;vite.config.ts&lt;/code&gt; file should look something like this now:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;defineConfig&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="s1"&gt;vite&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;react&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;basicSsl&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@vitejs/plugin-basic-ssl&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// https://vitejs.dev/config/&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;react&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;basicSsl&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 when you run the &lt;code&gt;npm run dev -- --host&lt;/code&gt; command, your dev server will run under the HTTPS protocol and the listed addresses will begin with &lt;code&gt;https://&lt;/code&gt;.&lt;br&gt;
After going to the listed address/port on your phone, you will see this warning message: &lt;code&gt;Your connection is not private (NET::ERR_CERT_AUTHORITY_INVALID)&lt;/code&gt; &lt;br&gt;
Tap on &lt;code&gt;Advanced&lt;/code&gt; and select the &lt;code&gt;Proceed to ... (unsafe)&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;🎉 Congratulations! now you can test/debug device orientation (gyroscope) on localhost using your phone!&lt;/p&gt;

</description>
      <category>vite</category>
      <category>tutorial</category>
      <category>typescript</category>
      <category>react</category>
    </item>
  </channel>
</rss>
