<?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: donocode</title>
    <description>The latest articles on DEV Community by donocode (@donocode).</description>
    <link>https://dev.to/donocode</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%2F580091%2F336fb990-6a58-4e13-911d-42c5fa4a1069.jpeg</url>
      <title>DEV Community: donocode</title>
      <link>https://dev.to/donocode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/donocode"/>
    <language>en</language>
    <item>
      <title>Using Mantine NavigationProgress with Remix</title>
      <dc:creator>donocode</dc:creator>
      <pubDate>Thu, 28 Jul 2022 19:19:56 +0000</pubDate>
      <link>https://dev.to/donocode/using-mantine-navigationprogress-with-remix-41i7</link>
      <guid>https://dev.to/donocode/using-mantine-navigationprogress-with-remix-41i7</guid>
      <description>&lt;p&gt;Today we are going to learn how to implement the &lt;a href="https://mantine.dev/others/nprogress/"&gt;NavigationProgress component from Mantine.dev&lt;/a&gt; in a remix application. The component will be used to indicate that there is some asynchronous process happening (loading content, navigating, form submission).&lt;/p&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;&amp;lt;NavigationProgress&amp;gt;&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Mantine has an additional package called &lt;code&gt;@mantine/nprogress&lt;/code&gt; which contains a single component and some utility functions for interacting with the component state. If you haven't installed it already &lt;a href="https://mantine.dev/others/nprogress/"&gt;follow the installation instructions first&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We are only concerned with the functions &lt;code&gt;startNavigationProgress&lt;/code&gt; to trigger the progress bar to start increasing and &lt;code&gt;resetNavigationProgress&lt;/code&gt; to reset and hide the progress bar. We will hook these up to Remix so that we start progress any time the UI is in a loading or submission state and reset progress every time the UI returns to the idle state.&lt;/p&gt;

&lt;p&gt;The component &lt;code&gt;&amp;lt;NavigationProgress&amp;gt;&lt;/code&gt; by default renders a progress bar in a React Portal, this is fine if you are rendering at the top of the viewport but otherwise you may have to &lt;a href="https://mantine.dev/others/nprogress/?t=props"&gt;adjust some of the default props&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Remix &lt;code&gt;useTransition&lt;/code&gt; hook
&lt;/h3&gt;

&lt;p&gt;Remix provides a &lt;a href="https://remix.run/docs/en/v1/api/remix#usetransition"&gt;useTransition&lt;/a&gt; hook that exposes the current state of any loaders or actions in your application. The hook exposes quite a lot of data about the transition such as what type of transition it is, and what the next location will be, but we are only interested in the &lt;code&gt;state&lt;/code&gt;. When there is no transition occurring &lt;code&gt;state&lt;/code&gt; will be &lt;code&gt;"idle"&lt;/code&gt; and otherwise it will be &lt;code&gt;"loading"&lt;/code&gt; or &lt;code&gt;"submitting"&lt;/code&gt; depending on the transition type.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing a &lt;code&gt;&amp;lt;GlobalLoadingIndicator&amp;gt;&lt;/code&gt; component
&lt;/h3&gt;

&lt;p&gt;Using this knowledge we can create a small component to link Remix transitions and NavigationProgress together.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&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="s2"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useTransition&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@remix-run/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;NavigationProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;resetNavigationProgress&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;startNavigationProgress&lt;/span&gt;&lt;span class="p"&gt;,&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;@mantine/nprogress&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GlobalLoadingIndicator&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;state&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTransition&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="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;state&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;idle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// we are idle so hide the progress bar&lt;/span&gt;
      &lt;span class="nx"&gt;resetNavigationProgress&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="c1"&gt;// we are doing something so show the progress bar&lt;/span&gt;
      &lt;span class="c1"&gt;// and allow it to increment&lt;/span&gt;
      &lt;span class="nx"&gt;startNavigationProgress&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;state&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// I set the stepInterval to 100 so it increases every 100 milliseconds&lt;/span&gt;
  &lt;span class="c1"&gt;// but you can set it to something that feels nice for your app&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="nc"&gt;NavigationProgress&lt;/span&gt; &lt;span class="na"&gt;stepInterval&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="si"&gt;}&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;h3&gt;
  
  
  Using your new component
&lt;/h3&gt;

&lt;p&gt;The final step to include the progress bar in your app is to render the &lt;code&gt;&amp;lt;GlobalLoadingIndicator&amp;gt;&lt;/code&gt; component in your layout somewhere that it can always be seen. In my case I render it inside the &lt;code&gt;&amp;lt;MantineProvider&amp;gt;&lt;/code&gt; in &lt;code&gt;root.tsx&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt; &lt;span class="na"&gt;lang&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Meta&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Links&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StylesPlaceholder&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;head&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;margin&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;MantineProvider&lt;/span&gt;
          &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;colorScheme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;withGlobalStyles&lt;/span&gt;
          &lt;span class="na"&gt;withNormalizeCSS&lt;/span&gt;
        &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Your usage may differ */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;GlobalLoadingIndicator&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Outlet&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;MantineProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ScrollRestoration&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Scripts&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;LiveReload&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;body&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;html&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great, now you have a basic implementation of the NavigationProgress component in your Remix application! You can play with the component props and reacting to the different transition types to improve the experience as you see fit.&lt;/p&gt;

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