<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Matthew Claffey</title>
    <description>The latest articles on DEV Community by Matthew Claffey (@mattc).</description>
    <link>https://dev.to/mattc</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%2F224245%2Fa9462a6a-3cfa-4861-a4fc-e4bb9f8b584e.jpg</url>
      <title>DEV Community: Matthew Claffey</title>
      <link>https://dev.to/mattc</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mattc"/>
    <language>en</language>
    <item>
      <title>5 reasons why data handling is easier with Redux Toolkit &amp; RTK Query</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Fri, 08 Dec 2023 13:31:46 +0000</pubDate>
      <link>https://dev.to/mattc/5-reasons-why-data-handling-is-easier-with-redux-toolkit-rtk-query-4i6i</link>
      <guid>https://dev.to/mattc/5-reasons-why-data-handling-is-easier-with-redux-toolkit-rtk-query-4i6i</guid>
      <description>&lt;p&gt;Have you ever come onto a project and you notice there are multiple ways to call apis and you just get confused to which to use? Some ways might be overly complicated for what you need to do, you don't know which one to use and then when you get to a code review you get told to use the other way?&lt;/p&gt;

&lt;p&gt;I wanted to find a way we could have a standardised way of calling apis so that the UI was kept simple and had information to use for the UI to display different states without having all that logic built in every time you needed to call an api. You normally get something like this…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&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;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;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="nf"&gt;useState&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;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setIsSuccess&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="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;fetch&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="k"&gt;try&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="nx"&gt;response&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;/api/users&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;200&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="nx"&gt;response&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;setIsSuccess&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;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="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="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="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="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="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;IsLoading&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="nx"&gt;isError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Error&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&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="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Empty&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overtime, this looks a bit mental. Nothing caters for caching here, it fetches every time the component mounts and it is not reusable in another component.&lt;/p&gt;

&lt;p&gt;In the project I was working on we was using redux anyway so I thought how could we use RTK query to make our lives easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  🤔 What is RTK Query?
&lt;/h2&gt;

&lt;p&gt;RTK Query is a tool you integrate with redux toolkit that makes handling data in your web apps a whole lot easier. It helps you fetch data from a server, manage it in your app, and keeps it up to date without all the usual headaches.&lt;/p&gt;

&lt;h2&gt;
  
  
  01. 📦 Creating apis
&lt;/h2&gt;

&lt;p&gt;RTK query only takes minutes to setup before you can start setting up API endpoints.&lt;/p&gt;

&lt;p&gt;📝 Example: This is our example of use setting up a basic set of APIS which get the user which share an authorisation token.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;createApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchBaseQuery&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;@reduxjs/toolkit/query/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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducerPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fetchBaseQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
    &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;prepareHeaders&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;headers&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;// Example if you need to apply a header on all apis&lt;/span&gt;
      &lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Authorization&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;Bearer TOKEN&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="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&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;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// /api/users&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;getUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;updateUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutation&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PATCH&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="na"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutation&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👍 Good for: Having a standardised way for setting up endpoints and sharing headers between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  02.🪝 React Hooks
&lt;/h2&gt;

&lt;p&gt;No more creating your own custom hooks for apis! RTK creates react hooks for you when you add a new endpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;createApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchBaseQuery&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;@reduxjs/toolkit/query/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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducerPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fetchBaseQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&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;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="c1"&gt;// /api/users&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;useGetUsersQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How awesome is that? That would have been about a solid day or two creating a fancy react hook that tries to solve all purposes that is now resolved as soon as you make a new endpoint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Queries
&lt;/h3&gt;

&lt;p&gt;As soon as the component mounts we fetch off to the api to get the data we need.&lt;/p&gt;

&lt;p&gt;📝 Example: Fetching all users showing different visual states.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useGetUsersQuery&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;../apis&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;Component&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="c1"&gt;// the response from the api&lt;/span&gt;
    &lt;span class="nx"&gt;isError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// has an error&lt;/span&gt;
    &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// first mount loading&lt;/span&gt;
    &lt;span class="nx"&gt;isFetching&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// is Fetching again after the first mount&lt;/span&gt;
    &lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// is 200&lt;/span&gt;
    &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="c1"&gt;// Error message&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetUserQuery&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="c1"&gt;// Purely for demo purposes&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;👍 Good for: Shared pattern across the app making it easier to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mutations
&lt;/h3&gt;

&lt;p&gt;Mutations allow you to make a change to an endpoint based on an action that has been fired in the app.&lt;/p&gt;

&lt;p&gt;📝 Example: Deleting a user when clicking a button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useDeleteUserMutation&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;../apis&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;Component&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;deleteUserPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeleteUserMutation&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;handleClick&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deleteUserPromise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userOne&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Delete user
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&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;👍 Good for: Shared pattern across the app making it easier to understand.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lazy Queries
&lt;/h3&gt;

&lt;p&gt;Lazy queries behave like mutations but are used more for get requests that you need to do after an action is called.&lt;/p&gt;

&lt;p&gt;📝 Example: Getting a user by id when you click a button.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useLazyGetUserQuery&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;../apis&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;Component&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;getUserPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// Same data as a query&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useLazyGetUserQuery&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;handleClick&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="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="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getUserPromise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userOne&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;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;setUser&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="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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        Get user
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;userName&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&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;👍 Good for: When you need get data from an action instead of on mount of a component.&lt;/p&gt;

&lt;h2&gt;
  
  
  👀 Watch out …
&lt;/h2&gt;

&lt;p&gt;Queries/Lazy Queries are cached endpoints by default so when you change some code with a mutation you might get a cached response from the queries ….&lt;/p&gt;

&lt;h2&gt;
  
  
  03. ⚙️ Let's fix that
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Default cache times
&lt;/h3&gt;

&lt;p&gt;The default cache time for a query is 60 seconds.&lt;br&gt;
When multiple components use the same hook, it will prevent the same api from being called multiple times which reduces overhead on your server 💰. When the first one is resolved, it is resolved for everywhere that calls it.&lt;/p&gt;

&lt;p&gt;📝 Example: Setting getUser to have 0 second cache.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;createApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchBaseQuery&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;@reduxjs/toolkit/query/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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducerPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fetchBaseQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&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;getUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;keepUnusedDataFor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="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;🕵️Tip: keepUnusedDataFor is good for apis that you need to get fresh data from every time. This also can be inherited when set at the top level api.&lt;/p&gt;

&lt;h3&gt;
  
  
  Invalidating caches with Tags
&lt;/h3&gt;

&lt;p&gt;Sometimes you just need to update the cache when you call a mutation. This is where RTK query provides you with Tags.&lt;/p&gt;

&lt;p&gt;📝 Example: Using tagTypes to define what tags I want to define. When deleteUser gets called it will invalidate anything with provideTags: ["Users"].&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;createApi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchBaseQuery&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;@reduxjs/toolkit/query/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;api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createApi&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;reducerPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;baseQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;fetchBaseQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;baseUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="na"&gt;tagTypes&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;Users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;endpoints&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;builder&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;getUsers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;provideTags&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;Users&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="na"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mutation&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DELETE&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;invalidatesTags&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;Users&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Refetching
&lt;/h3&gt;

&lt;p&gt;Now we have tags in place, we can use a method that returns back from the query called "refetch" which will get us the latest set of users when the deleteUser method has completed.&lt;/p&gt;

&lt;p&gt;📝 Example: When deleteUser is fired, it will invalidate the getUsers cache and then "refetch" will get a new set of users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useGetUsersQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useDeleteUserMutation&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;../apis&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;Component&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;refetch&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetUserQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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;deleteUser&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;isSuccess&lt;/span&gt; &lt;span class="p"&gt;}]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeleteUserMutation&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;handleClick&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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;deleteUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userTwo&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// even though the tag is invalidated, there&lt;/span&gt;
      &lt;span class="c1"&gt;// is nothing telling useGetUser to refetch the&lt;/span&gt;
      &lt;span class="c1"&gt;// the new cache&lt;/span&gt;
      &lt;span class="nf"&gt;refetch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;isSuccess&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Update user
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&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;
  
  
  04. 🔄 Other Features
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Polling
&lt;/h3&gt;

&lt;p&gt;RTK Query can take secondary params to change how often to re-fetch the data.&lt;/p&gt;

&lt;p&gt;📝 Example: Polling for changes to our get all users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useGetUsersQuery&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;../apis&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;Component&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetUserQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;polling&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Purely for demo purposes&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🟠Be careful: Use this pragmatically as it could become costly on the server side.&lt;/p&gt;

&lt;h3&gt;
  
  
  Automatic Refetching
&lt;/h3&gt;

&lt;p&gt;When a query takes params to fetch specific data, it will cache that specific request for 60 seconds. By making the query dynamic with query parameters, the data is passed into the hook updates the state returned as it calls a new endpoint path.&lt;/p&gt;

&lt;p&gt;📝 Example: Updating the user id when pressing the button which fetches the other user.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useGetUsersQuery&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;../apis&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;Component&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&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="s1"&gt;userOne&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;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetUserQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&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;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userTwo&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Update user
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&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;
  
  
  05. ⛓️ Dependency Management
&lt;/h2&gt;

&lt;p&gt;RTK Query can take secondary parameter called skip which will tell RTK to not call this api until the id is defined.&lt;/p&gt;

&lt;p&gt;📝 Example: Using skip parameter to prevent the query from being called.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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;useGetUsersQuery&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;../apis&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;Component&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUser&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;undefined&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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useGetUserQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;user&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;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;userTwo&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      Update user
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&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;
  
  
  💣 What doesn't do well?
&lt;/h2&gt;

&lt;p&gt;If you are like me who is a NextJS fanboy then you will have noticed that in version 13 there is a big buzz around server components and moving all JS code back to the server so we render more on the sever which makes the client faster. RTK is a client-side library so this does not work with server components.&lt;/p&gt;

&lt;h2&gt;
  
  
  🏁 Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, the main reason why I like using this tool is purely around DevEx. I like how multiple teams can easily adopt this library and then when you move around teams you can easily understand how these apis work as there is a standardised pattern of implementing endpoints across the app.&lt;br&gt;
Not only that the DevEx is good, it also makes my unit tests a lot nicer as I am mocking the variables that come from the react hooks which makes my confidence in my tests a lot higher as I can test more of the UI.&lt;/p&gt;

&lt;p&gt;This is not saying use RTK for everything, as there are many libraries that do this however if you are using toolkit on your project maybe have a look at this?&lt;/p&gt;

&lt;p&gt;What are your experiences using it?&lt;/p&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>reactnative</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Integrating Sentry.io with GatbsyJS</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sun, 31 Jan 2021 15:41:17 +0000</pubDate>
      <link>https://dev.to/mattc/integrating-sentry-io-with-gatbsyjs-16l4</link>
      <guid>https://dev.to/mattc/integrating-sentry-io-with-gatbsyjs-16l4</guid>
      <description>&lt;p&gt;When a web application has a lot of incoming traffic we want to have some form of logging to monitor errors across the domain so our application is performing at its best. In this article I am going to show you how to implement Sentry with GatsbyJS.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;If you wish to follow along with the tutorial here is what I used to get setup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Gatsby setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i gatsby -g

npm init gatsby
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sentry setup
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Register for a free account with &lt;a href="https://sentry.io/signup/"&gt;Sentry&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;install @sentry/gatsby --save-dev - &lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-sentry/"&gt;link&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;install @sentry/react --save&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;in gatsby-config.js write the following code:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gatsby-plugin-sentry&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;dsn&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;YOUR_SENTRY_DSN_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="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;If you wish to look at some code you can run &lt;strong&gt;gatsby new my-app&lt;/strong&gt; &lt;a href="https://github.com/code-mattclaffey/sentry-gatsby-example"&gt;&lt;strong&gt;https://github.com/code-mattclaffey/sentry-gatsby-example&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Providing a better user experience when something goes wrong
&lt;/h2&gt;

&lt;p&gt;The customer would normally get a "white screen of death" when an error happens and that completely stops the journey for a customer. This leads to a very high chance of the customer not purchasing your product and it can really leave a bad review if the error is not handled appropriately.&lt;/p&gt;

&lt;p&gt;In React, there's a pattern called an error boundary which contains the error within the scope to where sits in the tree for example; if we place the error boundary at the App level, it will handle all errors that happen within the App component. In Gatsby we want to apply this error boundary at the root of the Gatsby application. The api we are going to use is called &lt;a href="https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/#wrapPageElement"&gt;wrapPageElement&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the error boundary
&lt;/h3&gt;

&lt;p&gt;The first thing we want to do is to create a React component that handles when an error happens on the site. Since we are using Sentry for our logging we want to see if there's anything on npm already so we do not have to write any bespoke integration with Sentry. Luckily! Sentry does has an npm package called &lt;a href="https://www.npmjs.com/package/@sentry/react"&gt;@sentry/react&lt;/a&gt; which provides an error boundary component for us already use. Here is an example of some UI component we have made which is passed into the Sentry's ErrorBoundary component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ErrorBoundary&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;@sentry/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;Link&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;gatsby&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;Fallback&lt;/span&gt; &lt;span class="o"&gt;=&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;resetError&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alert&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;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Something&lt;/span&gt; &lt;span class="nx"&gt;went&lt;/span&gt; &lt;span class="nx"&gt;wrong&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&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="nx"&gt;pre&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;error&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/pre&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="nx"&gt;Link&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;resetError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Try&lt;/span&gt; &lt;span class="nx"&gt;again&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/a&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="nx"&gt;Link&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;/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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ErrorBoundaryContainer&lt;/span&gt; &lt;span class="o"&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;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorBoundary&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="nx"&gt;FallBack&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;/ErrorBoundary&lt;/span&gt;&lt;span class="err"&gt;&amp;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;ErrorBoundaryContainer&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once we have our component we need to add it to the page root in gatsby-browser.js.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ErrorBoundary&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;`./src/components/error-boundary&lt;/span&gt;&lt;span class="dl"&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;wrapPageElement&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;element&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;

  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ErrorBoundary&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;element&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;/ErrorBoundary&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Testing that it works
&lt;/h3&gt;

&lt;p&gt;If you wanna test this working simple throw an Error in your react application like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="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="s2"&gt;react&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;Component&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;toggleError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setToggleError&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="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toggleError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Component 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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="nx"&gt;onClick&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="nf"&gt;setToggleError&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="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Toggle&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Visualising the errors in Sentry.io
&lt;/h2&gt;

&lt;p&gt;Sentry has a really simple UI that displays when an error has happened on the site. Once that error gets captured it then gets displayed in the issues section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j4bP9RZH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/s4w9wwl5zonh/50p5OzToAUEKMqlxNKkTYM/e3d2b52cef29c83b866e0d4da8d73ec5/Screenshot_2021-01-31_at_14.34.33.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j4bP9RZH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/s4w9wwl5zonh/50p5OzToAUEKMqlxNKkTYM/e3d2b52cef29c83b866e0d4da8d73ec5/Screenshot_2021-01-31_at_14.34.33.png" alt="error-1" width="800" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When we click into the error it gives us a lot of information about the error such as the browser, operating system and error details that happened. I found this section really nice to work with and understand.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting up alerts that notify when an error has happened
&lt;/h2&gt;

&lt;p&gt;The next thing we want to do is to alert someone when we get an error. Sentry has the ability to setup alerting that emails a member of the group.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QunuV_s2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/s4w9wwl5zonh/2sRaOjpx5XvHnoGQimqkdr/9c8d8e7596aa5ac0583ba2bc8a8057d7/Screenshot_2021-01-31_at_14.40.31.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QunuV_s2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/s4w9wwl5zonh/2sRaOjpx5XvHnoGQimqkdr/9c8d8e7596aa5ac0583ba2bc8a8057d7/Screenshot_2021-01-31_at_14.40.31.png" alt="Error 2" width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the example I made an error with the message of "I crashed!" and I wanted to send myself an email so when the error fires within a 5 minute rate limit I will be notified about it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--d5DK6BHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/s4w9wwl5zonh/4Qu5RoUU12BMcOo6m8UqjO/0a434321143fda80d43e8138fdba6288/Screenshot_2021-01-31_at_14.43.55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--d5DK6BHW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://images.ctfassets.net/s4w9wwl5zonh/4Qu5RoUU12BMcOo6m8UqjO/0a434321143fda80d43e8138fdba6288/Screenshot_2021-01-31_at_14.43.55.png" alt="error-3" width="706" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In summary, adding logging/error handling in your react application is really easy to do. Sentry handles a lot the heavy shifting for us and Gatsby provides us with an api to stick our error boundary at the root of the component. With very little effort and very high value I believe this is such a good tool to use when building customer facing websites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.gatsbyjs.com/docs/reference/config-files/gatsby-browser/#wrapPageElement%20"&gt;How to add an error boundary to Gatsby root&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://docs.sentry.io/platforms/javascript/guides/react/"&gt;Getting started with Sentryio&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-plugin-sentry/"&gt;Gatsby Sentry plugin&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://reactjs.org/docs/error-boundaries.html"&gt;React Error Boundaries&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>gatsby</category>
      <category>sentry</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Responsive fonts using css clamp()</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Mon, 30 Nov 2020 14:46:39 +0000</pubDate>
      <link>https://dev.to/mattc/responsive-fonts-using-css-clamp-1h0f</link>
      <guid>https://dev.to/mattc/responsive-fonts-using-css-clamp-1h0f</guid>
      <description>&lt;p&gt;If you have wrote CSS for fonts before you have probably experienced having to introduce a lot of media queries for different breakpoints.&lt;/p&gt;

&lt;p&gt;A designer will provide designs for mobile/desktop and then the developer ends up asking “what about tablet?”, sound familiar? The output of those decisions could end up like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root {
  --heading-font-size: 3em;
  --heading-font-size-tablet: 6em;
  --heading-font-size-desktop: 9em;
}

body {
  font-size: 16px;
}

h1,
.h1 {
  font-size: var(--heading-font-size);
}

@media screen and (min-width: 48em) {
  h1,
  .h2 {
    font-size: var(--heading-font-size-tablet);
  }
}

@media screen and (min-width: 64em) {
  h1,
  .h2 {
    font-size: var(--heading-font-size-desktop);
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With technology changing so fast and new devices being released everyday our websites have to try and cater for those new screen sizes. Media queries solve only half the problem by setting fixed breakpoints at certain screen sizes. What if we could just make our fonts scale with no media queries and it’s implemented in one line of css? This is where CSS clamp() comes into the mix.&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS clamp()
&lt;/h3&gt;

&lt;p&gt;CSS clamp is a function that sets responsive unit sizes without any media queries. The function takes 3 parameters in this order:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;min — Where to start scaling from&lt;/li&gt;
&lt;li&gt;viewport width —The range determines how fast the min scales to the max based on the screen getting larger&lt;/li&gt;
&lt;li&gt;max —when to stop scaling
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clamp(min, viewport-width-unit, max);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Applying clamp() to our font example
&lt;/h3&gt;

&lt;p&gt;When using clamp with fonts I tend to make the range to be the maximum container width so when the browser is wider than that container, the font is at its maximum size. In the diagram below it shows how this works. In my example, my container is 80em (1280px) and my maximum font for my heading is 9em (144px).&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%2Fcdn-images-1.medium.com%2Fmax%2F861%2F1%2ASSuBipNt3oRDMCLvmowS2Q.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%2Fcdn-images-1.medium.com%2Fmax%2F861%2F1%2ASSuBipNt3oRDMCLvmowS2Q.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the browser width is greater than 80em the maximum font size will be 9em. When the browser width is less than 80em my font slowly starts to get smaller and smaller until it has reached 3em. Once 3em is reached, the browser stops shrinking the font size. This is how it looks in code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;:root {
  --global-h1-size: clamp(
    3em, 
    calc(9 / 80 * 100vw), 
    9em
  );
}

h1,
.h1 {
  font-size: var(--global-h1-size);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Browser support
&lt;/h3&gt;

&lt;p&gt;On &lt;a href="https://caniuse.com/mdn-css_types_clamp" rel="noopener noreferrer"&gt;CanIUse&lt;/a&gt; CSS clamp is supported in around 86.8% of browsers so it looks quite promising to use now in production code.&lt;/p&gt;

&lt;p&gt;A fallback suggestion could be to use css supports to put back in the media queries or set another font-size property before so when the browser does not recognise the clamp function it falls back to a default font-size. It depends on your target audience and how much conversion those browser bring to your website.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// IE11 is 9/10 a large screen so fallback to large size feels like a good solution
font-size: 9em;
font-size: clamp(3em, 11.5vw, 9em);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;And thats it! Using clamp makes your house styles for fonts a lot easier to manage across multiple screen sizes. I feel like this approach caters for a wider audience of device users where as the media query approach is quite fixed.&lt;/p&gt;

&lt;p&gt;When I discovered this I was in the middle of making some house styles for my website and I literally was baffled from how little code you have to write to make it work. This gif described the moment…&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%2Fcdn-images-1.medium.com%2Fmax%2F275%2F0%2A1waIGVT9ihDjU_-u.gif" 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%2Fcdn-images-1.medium.com%2Fmax%2F275%2F0%2A1waIGVT9ihDjU_-u.gif"&gt;&lt;/a&gt;Shia Labeouf Reaction GIF&lt;/p&gt;

&lt;p&gt;Heres a link to my CodePen which shows clamp in action.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codepen.io/code-mattclaffey/pen/dypoyzq" rel="noopener noreferrer"&gt;https://codepen.io/code-mattclaffey/pen/dypoyzq&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://vw.joealden.com/" rel="noopener noreferrer"&gt;https://vw.joealden.com/&lt;/a&gt; — really handy calculator tool that calculates the breakpoint width based on the font size.&lt;/p&gt;

</description>
      <category>frontend</category>
      <category>css</category>
      <category>cssclamp</category>
    </item>
    <item>
      <title>How to mock api calls in Storybook</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Mon, 21 Sep 2020 16:26:15 +0000</pubDate>
      <link>https://dev.to/mattc/how-to-mock-api-calls-in-storybook-1762</link>
      <guid>https://dev.to/mattc/how-to-mock-api-calls-in-storybook-1762</guid>
      <description>&lt;p&gt;The other day I was building a storybook page component and I was having issues where the page had a useEffect hook that hit an api from the dev environment to populate the state. There was a few issues with this because the data I was getting back needed an Id so it could a lookup in the database to find the record relating to the Id.&lt;/p&gt;

&lt;p&gt;This to me gave me a few red alerts because I couldn’t make my story look the way it would on the website. This blog post is about how you can work around that to enrich your stories and make them more effective when your components work with API’s.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why shouldn’t you just use the dev API for storybook?
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Maintaining page states
&lt;/h4&gt;

&lt;p&gt;Very hard to maintain multiple page states as you have no control of the data that is coming back. So if you wanted to display an error from that api, you can’t do that with ease because the backend api controls what comes back.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dependency on the database
&lt;/h4&gt;

&lt;p&gt;The record could get deleted which will break your story. If you have visual regression tests it will be picked up but if not you could have a broke story for a while depending on how often the story gets worked on.&lt;/p&gt;

&lt;h4&gt;
  
  
  Needs real data for the backend to consume
&lt;/h4&gt;

&lt;p&gt;Backend API’s have special requirements with what data you send in the body but all we care about is the different types of responses our page handles and thats hard to do when we have no control over it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Storybook middleware
&lt;/h3&gt;

&lt;p&gt;Storybook has a feature where you can setup API calls which can be used in your stories. Under the hood the middleware is an expressJS server so the syntax is really simple, for example:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;.storybook/middleware.js&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const express = require('express');
const bodyParser = require('body-parser');
​
​
const expressMiddleWare = router =&amp;gt; {
    router.use(bodyParser.urlencoded({ extended: false }));
    router.use(bodyParser.json());

    router.get(/api/get-orders/:orderId, (request, response) =&amp;gt; {
      if (request.params.orderId === 'error') {
        response.status(500).send('Something broke!')
      }

      res.send({ data: { text: 'hello world' } })

    })
};
​
​
module.exports = expressMiddleWare;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And thats it you have an api setup in storybook. If you hit that relative path on &lt;strong&gt;&lt;em&gt;localhost:9001/api/get-orders/123&lt;/em&gt;&lt;/strong&gt; it will respond with a success and if you send &lt;strong&gt;&lt;em&gt;localhost:9001/api/get-orders/error&lt;/em&gt;&lt;/strong&gt; you have forced an error state in your api so you can create two stories for your page component. Here is an example to how it would look in your story.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export const withSuccessfulOrder = () =&amp;gt; &amp;lt;Comp orderId="123" /&amp;gt;
export const withErrorOrder = () =&amp;gt; &amp;lt;Comp orderId="error" /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handling environments
&lt;/h3&gt;

&lt;p&gt;Some websites tend to have multiple api environments such as dev/staging/prod and they normally have an environment variable to define the api domain. So locally the frontend could be hitting the dev environment and then when that code goes into prod the api url is now the prod domain. It normally looks like this in your code..&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch(`${API_URL}/get-orders/${orderId}`).then((res) =&amp;gt; res.json())so on...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In storybook when we build our stories together the default env would need to be changed to api or whatever url you have setup in the middleware so the code replaces API_URL with our /api. Easy way to do this is by setting the env when you run the storybook build/serve command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API\_URL=/api storybook build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the code that references that env var will be /api and the example about will be /api/get-orders/${orderId} .&lt;/p&gt;

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

&lt;p&gt;That is pretty much it! We can now start writing more efficient stories that are a lot more dynamic and help us extend our development before switching over to testing it in the website. The benefits to mocking the apis in storybook are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The state is in our control so we can make our stories more accurate by sending the data we expect to come back from the api.&lt;/li&gt;
&lt;li&gt;It won’t change, the mock api won’t fall over or change behaviour like it could in a backend api.&lt;/li&gt;
&lt;li&gt;Once an api contract is in place with the developer building it, you both can work at the same time with no dependency on each other.&lt;/li&gt;
&lt;li&gt;Visual regression tests are more accurate.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>storybookbyreact</category>
      <category>storybook</category>
      <category>react</category>
    </item>
    <item>
      <title>Keeping your medium content fresh in your 11ty website using Github Actions and Netlify</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sun, 26 Jul 2020 13:37:50 +0000</pubDate>
      <link>https://dev.to/mattc/keeping-your-medium-content-fresh-in-your-11ty-website-using-github-actions-and-netlify-3df8</link>
      <guid>https://dev.to/mattc/keeping-your-medium-content-fresh-in-your-11ty-website-using-github-actions-and-netlify-3df8</guid>
      <description>&lt;p&gt;On my personal website I use Medium as my content platform so I can channel my content via multiple channels. This is great because it allows me to take advantage of medium’s rich text editor and the &lt;a href="https://github.com/code-mattclaffey/personal-site/blob/master/src/site/_data/blog.js"&gt;implementation&lt;/a&gt; is really easy to do in 11ty.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tech Stack
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://mattclaffey.co.uk/"&gt;Website&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The website is built by a popular framework called 11ty which is just a simple static site generator that helps you build Jamstack websites. It gets the medium data at the build time so it can build the blog pages before deploying them to Netlify.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem
&lt;/h3&gt;

&lt;p&gt;The problem with this approach is that my content has a dependency on Medium to trigger a webhook that will trigger my Netlify build but it doesn’t have anything like that unless you upgrade your account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solution
&lt;/h3&gt;

&lt;p&gt;The requirement I gave myself was to have the ability to keep my content fresh on the site. I post blog posts every couple of weeks so for me having a build at the end of the day is more than enough for what I wanted it to do.&lt;/p&gt;

&lt;p&gt;I needed to figure out a way to trigger a Netlify build everyday just to keep the blog content fresh on my website. Netlify has a feature called build hooks which allows you to hit a Netlify endpoint that will then trigger a Netlify build.&lt;/p&gt;

&lt;p&gt;You can access the build hooks in by going to Netlify —  &lt;strong&gt;Settings &amp;gt; Build &amp;amp; deploy &amp;gt; Continuous deployment &amp;gt; Build hooks&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--akUNXxPH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AMsqhjgltFIkc_uCW.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--akUNXxPH--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/0%2AMsqhjgltFIkc_uCW.png" alt="" width="800" height="236"&gt;&lt;/a&gt;Credit to Netlify website — &lt;a href="https://docs.netlify.com/configure-builds/build-hooks/"&gt;&lt;/a&gt;&lt;a href="https://docs.netlify.com/configure-builds/build-hooks/"&gt;https://docs.netlify.com/configure-builds/build-hooks/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the build hook is setup the next thing to do is to setup a Github action to hit this build hook endpoint every day or so. For example:&lt;/p&gt;

&lt;p&gt;.github/workflows/main.yml&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name: "Netlify Trigger - Get updates from Medium"

on:

schedule:

- cron: '0 0 \* \* \*'

jobs:

curl:

runs-on: ubuntu-latest

steps:

- name: curl

uses: wei/curl@v1

with:

args: -X POST -d {} https://api.netlify.com/build\_hooks/${{ secrets.NETLIFY\_BUILD\_HOOK }}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This takes around 20s…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note — make sure the build hook id is stored in your Github secrets so no one can spam your Netlify builds.&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;The nicer approach to this would have been having a webhook that listens to an event from Medium to see when a new blog post has been added but to get you up and running a cron job daily seem to do the trick.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Build hooks with Netlify &lt;a href="https://docs.netlify.com/configure-builds/build-hooks/"&gt;https://docs.netlify.com/configure-builds/build-hooks/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Run your Github Actions workflow on a schedule &lt;a href="https://jasonet.co/posts/scheduled-actions/"&gt;https://jasonet.co/posts/scheduled-actions/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>githubactions</category>
      <category>jamstack</category>
      <category>netlify</category>
      <category>11ty</category>
    </item>
    <item>
      <title>Demystifying React Context</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sun, 26 Jul 2020 11:33:16 +0000</pubDate>
      <link>https://dev.to/mattc/demystifying-react-context-i9h</link>
      <guid>https://dev.to/mattc/demystifying-react-context-i9h</guid>
      <description>&lt;p&gt;Yesterday I spent some time learning about how to use the context and when I read the docs I thought, “this sounds extremely complex for something that does a simple thing”. I definitely felt like this at first:&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%2Fi%2Fkmv3c2d1m8vqopud7oe7.gif" 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%2Fi%2Fkmv3c2d1m8vqopud7oe7.gif" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After playing around with the code and learning more about the different ways of using it. I thought it would be good to share it with people who may feel the same as I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is React Context?
&lt;/h2&gt;

&lt;p&gt;Before this feature came out we had to pass our props down into each component and then repeat the same process again and again into our components. This becomes quite nasty over time and it can potentially end up with issues with the props being so deeply nested in our components.&lt;br&gt;
React Context is built to solve all of our problems because it removes the need for us to pass props down into our components. Instead, the components will inherit the props when nested within a context provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Less talking, more coding!
&lt;/h2&gt;

&lt;p&gt;Now let’s actually get some code up and running so we can see what the context is doing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — creating our context object
&lt;/h3&gt;

&lt;p&gt;The first thing we have to do is we need to create our context.&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%2Fi%2Fa49rjqe63p0yssq9fj2d.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%2Fi%2Fa49rjqe63p0yssq9fj2d.png" alt="Context setup"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the code there is a method that is on the React module called createContext . Now this is in place we can either carry on and make our provider or we can set a defaultValue as a parameter in the createContext method.&lt;/p&gt;

&lt;p&gt;The default value will only apply those values when a provider is not wrapped around the consumers. I will go into more detail on this in the defaultValue section.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2 — Apply the provider
&lt;/h3&gt;

&lt;p&gt;The createContext method gives the ability to use two components which are bound to the method which are Provider &amp;amp; Consumer . A provider is a component that gives the ability to set data which can be accessed by consumer components without passing any props.&lt;/p&gt;

&lt;p&gt;The component only takes one prop which is called value.&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%2Fi%2Fwotme84z0l381q2ss5ot.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%2Fi%2Fwotme84z0l381q2ss5ot.png" alt="Context provider"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3 — Setup the consumers
&lt;/h3&gt;

&lt;p&gt;The Consumer component is used to get data from the Provider which will then pass data into the components that live nested in theConsumer. There are 3 ways to implement a Consumer.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method one — using the Consumer component
&lt;/h4&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%2Fi%2Fudp9ntqtprd9fjjskwvv.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%2Fi%2Fudp9ntqtprd9fjjskwvv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We now have added a Paragraph component which has the DataContext.Consumer inside. This returns a function that gives us access to the properties set in the Provider. This way is useful to do with components that do not need any logic. So how can we do this with a component that has logic?&lt;/p&gt;

&lt;h4&gt;
  
  
  Method number 2 — using this.context &amp;amp; contextType
&lt;/h4&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%2Fi%2Fcct2uzszhtrn8ybcilv0.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%2Fi%2Fcct2uzszhtrn8ybcilv0.png" alt="Method number 2 — using this.context &amp;amp; contextType"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In components that use classes there is another way you can get access to the contexts data. As you can see, when we create our class we have underneath it the Paragraph.contextType = DataContext; and what this will do is it will give the class a property call context which is how we get access to our values that our provider are passing down.&lt;/p&gt;

&lt;h4&gt;
  
  
  Method 3 — using hooks
&lt;/h4&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%2Fi%2F79iym3ny4yekctgyxonn.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%2Fi%2F79iym3ny4yekctgyxonn.png" alt="Method 3 — using hooks"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Both solutions above do work and thats fine but we have to do two different methods to make it work for each component. useContext method is used to get the props from the context the same way as the two above but it is a lot simpler to look at. It looks very similar to the way you get props from this.props but the syntax differs a little because you’re calling useContext instead.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wait Matt, what about defaultValue ?
&lt;/h2&gt;

&lt;p&gt;As mentioned about I spoke briefly about how we can set defaultValues to our context and what this will do is if we do not have a provider wrapped around our components then our consumers will use the defaultValue that is set in createContext as a fallback.&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%2Fi%2F93kbt0815wsmkaq0buwo.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%2Fi%2F93kbt0815wsmkaq0buwo.png" alt="Default value to context"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have removed the Provider from our paragraph and set the values that used to be in the value prop inside our createContext function. This took me so long to figure out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I hope this made it a lot more clearer for everyone! Like I said I learnt this a few days ago so there is probably a lot more to the Context method. I hope this has cleared up some confusion over the topic as it definitely did confuse me at first.&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%2Fi%2Fndnru6d83x59ow5hb855.gif" 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%2Fi%2Fndnru6d83x59ow5hb855.gif" alt="Lord of the rings gif"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Loading Fonts The FOUT Way</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sun, 26 Jul 2020 11:21:53 +0000</pubDate>
      <link>https://dev.to/mattc/loading-fonts-the-fout-way-1gbi</link>
      <guid>https://dev.to/mattc/loading-fonts-the-fout-way-1gbi</guid>
      <description>&lt;h2&gt;
  
  
  How a font works in the browser?
&lt;/h2&gt;

&lt;p&gt;Fonts have the potential to be extremely slow. The more you include the more it can impact multiple metrics such as page weight, page load, first paint and first contentful paint.&lt;/p&gt;

&lt;h2&gt;
  
  
  What performance issues can occur?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Chain requests
&lt;/h3&gt;

&lt;p&gt;A chain request is when a resource that is required by another file instead of the document. When you add font-face inside a css file it will have a dependency on the css file to load before it can load the font in the browser. This can be a problem especially on slow connections because the HTML could take a second to load, then a second for your CSS and then an extra 1–2 seconds for the fonts to load. That is a total of 4 seconds where the user has not seen any text.&lt;br&gt;
When the fonts are slow you can tell all of a sudden seeing no text and then a “blink” and they all appear in the browser. Which is known as FOIT (flash of invisible text).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is FOIT
&lt;/h2&gt;

&lt;p&gt;Flash of invisible text is when the text on a website is invisible and then when the fonts have loaded they appear on the page. The text is rendered on the page ready but the browser does not know what font to use until they have loaded. When loaded, the the browser will “re-paint” the screen and show the new font, see how FOIT works (does contain flashing images).&lt;br&gt;
We want to remove this “blink” effect and try to have some form of content there so the user can get a feel for what message the website is trying to send quicker than having to wait for the font to load. This is called FOUT (Flash of un-styled text).&lt;/p&gt;

&lt;h2&gt;
  
  
  What is FOUT
&lt;/h2&gt;

&lt;p&gt;Flash of un-styled text is a popular concept where the user will see the fallback font before seeing the main font that we load in. When implemented we no longer see the invisible font. See how this would work here (does contain flashing images).&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing FOUT on your website
&lt;/h2&gt;

&lt;p&gt;So the easiest and quickest way on implementing FOUT is by using a css property called font-display. Font display is added to the font-face and it tells the browser what to do with the font when it is loading. You have a few values that you can have on this property but the main ones we want to do are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;swap — forces the browser to swap the font families out&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now let’s see what that would look like in our code...&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%2Fi%2F7o4mc8rdgvusoi0hopbq.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%2Fi%2F7o4mc8rdgvusoi0hopbq.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Extra bonus points!
&lt;/h2&gt;

&lt;p&gt;That is amazing we now get fonts in a little faster but if you are like me and want to make it blazingly fast lets dive deeper into what we can do. The way the fonts load is still the same. As mentioned above we have a chain request where the fonts are dependant on the css loading before it can load itself. Lets sort that out…&lt;/p&gt;

&lt;h3&gt;
  
  
  Embedding CSS
&lt;/h3&gt;

&lt;p&gt;First thing we can do is embed our font-face css in the html document. Downside to this is not being able to cache the embed code but if your fonts are about 10–30 lines of css then it is not a massive problem.&lt;/p&gt;

&lt;p&gt;For example:&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%2Fi%2Fszrke25u1u3a7uivopzv.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%2Fi%2Fszrke25u1u3a7uivopzv.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now what will happen is that the font will load regardless of the css. When the css has loaded, if the font has loaded by then it will swap the font font out faster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Resource hints
&lt;/h3&gt;

&lt;p&gt;The next thing we can do is use a resource hint called “preload”. Preloading a font will tell the network that this font wants to be loaded before anything else. The network will then treat the font as a critical resource and prioritise it when loading assets. Preloading is your friend, but preloading everything has the opposite effect and can make the site load normal again so make sure you prioritise which fonts you want to load. A good starting point is headings and body copy.&lt;/p&gt;

&lt;p&gt;For example:&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%2Fi%2Fjgj6u1j400wm8kugwtxd.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%2Fi%2Fjgj6u1j400wm8kugwtxd.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Preload is awesome to use on more than just fonts, the browser support is pretty good it is just ie 11 and Firefox that do not support the feature. Firefox does have this feature if you enable the feature under a flag in dev tools see more on CanIUse.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hidden gems
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Local property
&lt;/h3&gt;

&lt;p&gt;This is a gamer changer! Especially if you are using fonts such as Helvetica on your website. On apple devices Helvetica is installed locally so when the user comes to your website you can tell your css to pick the local font over the one on your server. How neat right?&lt;/p&gt;

&lt;p&gt;For example:&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%2Fi%2Ff167dpho1liftk8fsodn.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%2Fi%2Ff167dpho1liftk8fsodn.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: make sure you add local first because the order is important on the src property.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So we have learnt about fixing critical requests in the browser, how to implement FOUT and how to add extra hidden gems to make your fonts load blazingly fast!&lt;/p&gt;

</description>
      <category>performance</category>
      <category>javascript</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>Lazy Loading Images 2020</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sun, 26 Jul 2020 11:14:13 +0000</pubDate>
      <link>https://dev.to/mattc/lazy-loading-images-2020-5573</link>
      <guid>https://dev.to/mattc/lazy-loading-images-2020-5573</guid>
      <description>&lt;p&gt;Lazy loading is a concept where you only load the images within the viewport of the device the user is in. As the user navigates around the site, images will load in on demand. This makes a massive improvement on the page weight, which then has a domino effect on the load time due to less requests coming in on initial load of the page.&lt;/p&gt;

&lt;p&gt;Let’s go through how implementing the current way of lazy loading.&lt;/p&gt;

&lt;h2&gt;
  
  
  Implementing lazy loading
&lt;/h2&gt;

&lt;p&gt;My go-to plugin is called LazySizes because it is really easy to setup, has multiple add-ons, features that extend the current functionality and it is lightweight. It has a mixture of ways of how to implement the script but in this example I am just loading it from git CDN.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--K62xp8AU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/1lsrdg23r8otm22s9ddd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--K62xp8AU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/1lsrdg23r8otm22s9ddd.png" alt="Alt Text" width="800" height="166"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Before implementing lazy loading we have two images, a plain img tag and a responsive image:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E0nkOgA3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/obphvuttx5mdonnhobor.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E0nkOgA3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/obphvuttx5mdonnhobor.png" alt="Alt Text" width="800" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When implementing lazy loading for a standalone image it is pretty straight forward. All we need to do is add the lazyload class name to the image and then change the src attribute to data-src and that’s it! With picture elements it is a little different because you need to apply data-srcset to the source elements. Without it, they will load the image in regardless of the src on the image tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aghyXYqt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6x5oupjvmxejf94bmy0v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aghyXYqt--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/6x5oupjvmxejf94bmy0v.png" alt="Alt Text" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What do we do to make this SEO friendly?
&lt;/h2&gt;

&lt;p&gt;Google crawls pages and get all of the images on the page to then put them in Google image search. It looks for the src attribute on the image but we have changed that to the data-src attribute for our lazy loading so they no longer able to put the images on image search.&lt;br&gt;
Under the hood, LazySizes does some magic to make this work but as a safety net it is always good practice to provide a no JavaScript fallback.&lt;/p&gt;

&lt;p&gt;If no JavaScript is enabled on a browser the user will not be able to see the images as there is a dependency on the images loading via our JavaScript library. So we need to add a fallback to make those images are visible. This is done with a mix of css/html/js, in the example below we:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;add the no-js class to the html&lt;/li&gt;
&lt;li&gt;add the css in the page to hide lazyload elements&lt;/li&gt;
&lt;li&gt;add the JavaScript in which will remove the no-js class&lt;/li&gt;
&lt;li&gt;finally, provide a noscript tag of the image in its previous lazy loading state&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZN9br65s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/1xr7j7ssk1iu6robfihg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZN9br65s--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/1xr7j7ssk1iu6robfihg.png" alt="Alt Text" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that that is pretty much it, but we are in 2020 now and surely there is other ways of doing this right? My friend, let me introduce you to the native lazy load…&lt;/p&gt;

&lt;h2&gt;
  
  
  The future of lazy loading plugins?
&lt;/h2&gt;

&lt;p&gt;Lazy loading has a new kid on the block which is called native lazy loading. Native lazy loading is a feature first released by Google Chrome which allows you to set lazy loading on your image. It is also now supported in the last two versions of Edge which leads to around 63% global coverage across all browsers.&lt;/p&gt;

&lt;p&gt;It is really easy to implement, all you have to do is add an attribute on the img called loading and define one of the following as its value:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;auto — default lazy loading behaviour of the browser which is the same as not including the attribute&lt;/li&gt;
&lt;li&gt;lazy — defer loading of the resource until it is reached in the viewport&lt;/li&gt;
&lt;li&gt;eager — load the resource as soon as behaviour regardless of where it sits on the page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gk-ByzBo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/kepqc53opbyp8rqlo48v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gk-ByzBo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/kepqc53opbyp8rqlo48v.png" alt="Alt Text" width="800" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Is it time to stop using lazy loading plugins?
&lt;/h2&gt;

&lt;p&gt;I don’t think so, loading attribute only works for images and iframes but does not support background images. It also has a less aggressive threshold for loading images as it loads images in quite far down the page whereas lazysizes has a control to change the threshold for when you want the images to load in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Can we use both? Absolutely!
&lt;/h2&gt;

&lt;p&gt;We can check for native lazyload support in JavaScript which will then change all the data-src attributes to src attributes if the feature is supported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kolXbthg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/d076cw3b582dwuyw3mgt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kolXbthg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/d076cw3b582dwuyw3mgt.png" alt="Alt Text" width="800" height="698"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need lazy loading for background images then it is okay to leave the lazysizes script in the page as if but if you only use it for images then it might be worth loading the script in when the feature is not supported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cVZB-MmU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/5xy4imvwupvnb2nl1yek.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cVZB-MmU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/i/5xy4imvwupvnb2nl1yek.png" alt="Alt Text" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In conclusion we still need to be using lazy loading plugins but the new native feature can work along side with these plugins which makes the transition over to native a lot more smoothly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Addy Osmani— Native Lazyloading for the web — &lt;a href="https://addyosmani.com/blog/lazy-loading/"&gt;https://addyosmani.com/blog/lazy-loading/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Lazy Sizes — &lt;a href="https://github.com/aFarkas/lazysizes"&gt;https://github.com/aFarkas/lazysizes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;How to apply no js fallback — &lt;a href="https://stackoverflow.com/questions/22203063/how-to-write-css-fallbacks-for-when-javascript-is-disabled"&gt;https://stackoverflow.com/questions/22203063/how-to-write-css-fallbacks-for-when-javascript-is-disabled&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Responsive images — &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images"&gt;https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>lazyloading</category>
      <category>javascript</category>
      <category>performance</category>
      <category>sitespeed</category>
    </item>
    <item>
      <title>How to reduce you html output in 11ty</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sat, 25 Apr 2020 15:07:02 +0000</pubDate>
      <link>https://dev.to/mattc/how-to-reduce-you-html-output-in-11ty-e7c</link>
      <guid>https://dev.to/mattc/how-to-reduce-you-html-output-in-11ty-e7c</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--WDaJxA7Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AXenGkM5kGx-LlMl2xx8CYg.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--WDaJxA7Z--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AXenGkM5kGx-LlMl2xx8CYg.jpeg" alt="" width="800" height="257"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Minifying html is a really useful feature that can improve TTFB on the page and with 11ty it is very simple to do. In the eleventy.js config file we need to add a transform to the config which will check if the output is a .html file and if it is we will use an npm plugin called &lt;a href="https://www.npmjs.com/package/html-minifier%5C"&gt;html-minifier&lt;/a&gt; to compress our html code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--CLyqHaVP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A4iRnWjsbE6aVhEC8KNZQzQ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--CLyqHaVP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2A4iRnWjsbE6aVhEC8KNZQzQ.png" alt="" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra’s!
&lt;/h3&gt;

&lt;p&gt;If you use CSS modules in a react project then this concept will be straight forward but for those who haven’t done this there is a way to shorten our css selectors and then that will get reflected in the html too.&lt;/p&gt;

&lt;p&gt;Using a plugin &lt;a href="https://github.com/posthtml/posthtml-minify-classnames"&gt;posthtml-minify-css-classnames&lt;/a&gt; we can get our selectors shortened into small identifiers which will make our html output even smaller. This can be used with html, css and javascript inside the html document.&lt;/p&gt;

&lt;h4&gt;
  
  
  Before Vs After
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xvggrsHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aoc45IOALlBLbtAlZ3tZMwA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xvggrsHI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2Aoc45IOALlBLbtAlZ3tZMwA.png" alt="" width="800" height="498"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0hO1JsGW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ATjbEMd-ZiCapfwXvu7_fyA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0hO1JsGW--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2ATjbEMd-ZiCapfwXvu7_fyA.png" alt="" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In eleventy.js we need to apply the css class names change before we apply the minify on top.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UujdgUgr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AfwIRzk2xvljX2HlCtN9q2g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UujdgUgr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AfwIRzk2xvljX2HlCtN9q2g.png" alt="" width="800" height="577"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Results (Fast 3G test)
&lt;/h3&gt;

&lt;p&gt;In my example I managed to reduce my html output by around 11%.&lt;/p&gt;

&lt;p&gt;Before I implemented this I had un-minified html and my css was in a seperate file.&lt;/p&gt;

&lt;p&gt;Pro’s:&lt;/p&gt;

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

&lt;p&gt;Con’s&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;critical chain request&lt;/li&gt;
&lt;li&gt;takes longer to load&lt;/li&gt;
&lt;li&gt;unable to do it on a file basis it all needs to live in the html document.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0sHR7lEL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/848/1%2Av5mHe0cW6Xy_a9tTAPjLJw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0sHR7lEL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/848/1%2Av5mHe0cW6Xy_a9tTAPjLJw.png" alt="" width="800" height="52"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After the implementation we managed to reduce the load of the html and css from 1.21s to 0.592s which is nearly a 50% reduction in time it took.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NgzcMXYR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/825/1%2AXObZPHTR5pQ6Qs4kZRE3oA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NgzcMXYR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/825/1%2AXObZPHTR5pQ6Qs4kZRE3oA.png" alt="" width="800" height="60"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Resources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;11ty How to minify your html output — &lt;a href="https://www.11ty.dev/docs/config/#transforms-example-minify-html-output"&gt;https://www.11ty.dev/docs/config/#transforms-example-minify-html-output&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;html-minfier — &lt;a href="https://www.npmjs.com/package/html-minifier"&gt;https://www.npmjs.com/package/html-minifier&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;posthtml-minify-css-classnames — &lt;a href="https://github.com/posthtml/posthtml-minify-classnames"&gt;https://github.com/posthtml/posthtml-minify-classnames&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webperf</category>
      <category>eleventy</category>
      <category>performance</category>
      <category>html</category>
    </item>
    <item>
      <title>My favourite talks at DotCSS Paris</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Mon, 23 Dec 2019 14:19:06 +0000</pubDate>
      <link>https://dev.to/mattc/my-favourite-talks-at-dotcss-paris-2k03</link>
      <guid>https://dev.to/mattc/my-favourite-talks-at-dotcss-paris-2k03</guid>
      <description>&lt;p&gt;Day one was focused around CSS and each talk was truly inspiring. Here are a couple of talks that really stood out for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--T0RxalLd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AUI_r_it2zh9yMkLBKu7EGw.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--T0RxalLd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1024/1%2AUI_r_it2zh9yMkLBKu7EGw.jpeg" alt="" width="800" height="333"&gt;&lt;/a&gt;Conference main room (&lt;a href="https://www.dotjs.io/"&gt;&lt;/a&gt;&lt;a href="https://www.dotjs.io/"&gt;https://www.dotjs.io/&lt;/a&gt;)&lt;/p&gt;

&lt;h3&gt;
  
  
  Sarah Dayan — Utility based design systems
&lt;/h3&gt;

&lt;p&gt;The first talk was about Utility based design systems. Sara explained how to build design systems/style guides more efficiently using the utility based classes. The talk went over how using utility based classes can not only improve performance on the CSS bundle but it can also provide a better html output via Gzip.&lt;/p&gt;

&lt;p&gt;What I liked about this talk was the fact that Sara made the idea of using utility based classes very reasonable because it has performance benefits from a css/html prospective and to me thats a big win! Like any other developer, I hate repeating myself so if I can write those styles once and then use those class names wherever on the site it is a big win.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://noti.st/sarahdayan/pmD0XT/in-defense-of-utility-first-css?source=post_page-----d73c60541a35----------------------#sRrlfCN"&gt;In Defense of Utility-First CSS by Sarah Dayan&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Aurélien Levy- The double faces of CSS
&lt;/h3&gt;

&lt;p&gt;This is the type of talk that everyone loves! Straight to the point with lots of juicy tips to take back and implement with ease. &lt;a href="https://twitter.com/goetsu?lang=en"&gt;Aurélien Levy’s&lt;/a&gt; talk purely focused around what common a11y bugs he finds on websites he audits on a day to day.&lt;/p&gt;

&lt;p&gt;The hidden gem I found in this talk was not to add display: contents; to any elements. Aurélien showed everyone what happens if you add that to your elements and it just completely changed the way the screen reader read out the content that lived within the element. What that property will do is that it will remove all the semantics from that element and just read out plain text. So for screen reader users, they will not know what they are currently on because it will just read out plain text. So definitely one to remember!&lt;/p&gt;

&lt;h3&gt;
  
  
  Emily Plummer — CSS &amp;amp; Developer Experience
&lt;/h3&gt;

&lt;p&gt;This was by far my favourite talk of the day because of how relevant it is to what I am doing at the minute on my side project. Emily talked about how Github has managed to find a good balance between developer experience &amp;amp; customer experience and explains why it is good to have both. The talk was mainly focused around how Github implemented a design system and how it brought a fine balance between writing code the right way &amp;amp; delivering a product faster to our users. The main benefits that she went over were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delivery — developers had less things to worry about because the code was made up of small components which where plug in and play&lt;/li&gt;
&lt;li&gt;Testing — each component was individually unit tested which would allow more frequent releases&lt;/li&gt;
&lt;li&gt;Accessibility — bringing components into one single source of truth where the markup is only in one place really helped with keeping things accessible&lt;/li&gt;
&lt;li&gt;Design consistency — similar to the above, with the css class names in one place meant that it was easier to keep aligned with the designs&lt;/li&gt;
&lt;li&gt;Autonomy — a lot of the component logic was hidden within each component and had its own documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://drive.google.com/file/d/1U_6ptLiw4G0aYQpgW-Dk5CQ4H_u92f0Q/view?source=post_page-----d73c60541a35----------------------"&gt;DOTCSS.pdf&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Jason Pamental — Variable fonts and dynamic typography with CSS
&lt;/h3&gt;

&lt;p&gt;Frontend developers face quite a few problems when it comes to implementing fonts. We have to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Design Consistency&lt;/li&gt;
&lt;li&gt;Accessibility&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Finding the right balance between the fonts loading fast &amp;amp; them meeting design requirements can be a difficult problem to solve.&lt;/p&gt;

&lt;p&gt;Modern browser now have a feature called variable fonts that can provide a better solution that ticks all the boxes for developers, designers but more importantly, the end users.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://twitter.com/jpamental"&gt;Jason&lt;/a&gt;’s talk is about how variable fonts can provide a better solution which meets the requirements mentioned above.&lt;/p&gt;

&lt;h4&gt;
  
  
  What is a variable font?
&lt;/h4&gt;

&lt;p&gt;For people who are new to variable fonts it can be tricky to get a grasp around them. I definitely did!&lt;/p&gt;

&lt;p&gt;A variable font is a collection of font styles all bundled into one font. For a website to have multiple font styles we would have to include a font for each style whereas a variable font you may only need to include the one that caters for all. Then after that we just need to add the css in and we are good to go with them!&lt;/p&gt;

&lt;p&gt;Browser support for variable fonts seems to be at a decent 87.98% coverage too so it’s definitely something to play around with and try out.&lt;/p&gt;

&lt;p&gt;What I liked as well about this is that Jason mentioned about how we can actually start using variable fonts now in the browser as the font safely falls back to using the normal fonts in browsers that do not support it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://rwt.io/typography-tips/variable-fonts-opening-door-whole-new-typography"&gt;Variable Fonts: opening the door to whole new typography&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://noti.st/jpamental/Z0MwNQ/dynamic-typographic-systems-with-variable-fonts?source=post_page-----d73c60541a35----------------------"&gt;Dynamic Typographic Systems with Variable Fonts by Jason Pamental&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lightning Talks
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Fabien Zibi — CSS tests
&lt;/h4&gt;

&lt;p&gt;Now this I thought was a game changer, I have never thought you could write tests on sass functions and mixins but it turns out that you can quite simply with snapshots using Jest! Who knew!&lt;/p&gt;

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

&lt;p&gt;Overall it was a top day and I would definitely recommend attending this conference as it had great speakers, great facilities, great food and also it had a couple of foosball tables! What more can you want from a conference? :)&lt;/p&gt;

</description>
      <category>dotcss</category>
      <category>dotcss2019</category>
      <category>css</category>
    </item>
    <item>
      <title>Storing an array of elements using the useRef hook</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sat, 10 Aug 2019 15:59:51 +0000</pubDate>
      <link>https://dev.to/mattc/adding-react-refs-to-an-array-of-items-3lik</link>
      <guid>https://dev.to/mattc/adding-react-refs-to-an-array-of-items-3lik</guid>
      <description>&lt;p&gt;Storing an array of elements using the useRef hook&lt;br&gt;
React refs are useful for when we have to set focus to an element after the user has interacted with it. In my case, I needed to use refs for setting focus to the correct accordion item when I selected/used arrow keys.&lt;/p&gt;

&lt;p&gt;The problems I faced while doing this was a mixture of having issues with passing down refs into my components but also having one ref that represented an array of items just as you would in a none react app using document.querySelectorAll().&lt;/p&gt;
&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;When there is only one ref we tend to simply assign our ref value with the variable that creates the useRef function.&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;item&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&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;In my use case I could not simply assign my ref to the element because the ref was being assigned within a map during the render. This would mean that the very last item in the array would be the element assigned to item.current.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;The ref prop gives us the element as a parameter which allows us to assign the element however we want. In the example, we push that element into the itemsEls.current array so it can be used further down the line.&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;itemEls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;element&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;itemEls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&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;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: The same approach applies for an object with ids as a key.&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;itemEls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;({})&lt;/span&gt;

&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;element&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;itemEls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;element&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;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And thats it! We can now store an array of refs in one variable to use when the use case crops up.&lt;/p&gt;

&lt;p&gt;Note: this example of assigning a ref to a p tag is purely for simplicity of the code. A good use case for this is when building things that need focus applying to them when the user interacts with the component like an Accordion/Tabs/Modal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;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;useRef&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="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;items&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;itemsEls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;item&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;getRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&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;itemsEls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;element&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;p&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getRef&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;item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thank you for reading.&lt;/p&gt;

</description>
      <category>reactrefstutorial</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The PWA game</title>
      <dc:creator>Matthew Claffey</dc:creator>
      <pubDate>Sun, 21 Jul 2019 18:52:40 +0000</pubDate>
      <link>https://dev.to/mattc/the-pwa-game-2375</link>
      <guid>https://dev.to/mattc/the-pwa-game-2375</guid>
      <description>&lt;p&gt;&lt;a href="https://medium.com/@mattclaffey/the-pwa-game-856477e09728?source=rss-a21dfccbfdd4------2"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mQtyB6iQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn-images-1.medium.com/max/1642/1%2A0nSLsocpWbYsxQDPB7lP0Q.png" alt="" width="800" height="292"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Offline is becoming a standard thing to do in web applications because they allow your website to feel like an app. In the modern web most…&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/@mattclaffey/the-pwa-game-856477e09728?source=rss-a21dfccbfdd4------2"&gt;Continue reading on Medium »&lt;/a&gt;&lt;/p&gt;

</description>
      <category>offlinefirst</category>
      <category>frontend</category>
      <category>progressivewebapp</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
