<?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: Rupesh Ghosh</title>
    <description>The latest articles on DEV Community by Rupesh Ghosh (@ghostkeeper10).</description>
    <link>https://dev.to/ghostkeeper10</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%2F1058789%2Ff636f032-5a20-4589-b1b4-5114d3aaf548.png</url>
      <title>DEV Community: Rupesh Ghosh</title>
      <link>https://dev.to/ghostkeeper10</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ghostkeeper10"/>
    <language>en</language>
    <item>
      <title>How to Implement a Global Error Handling Popup in React Native with React Query</title>
      <dc:creator>Rupesh Ghosh</dc:creator>
      <pubDate>Sun, 19 May 2024 19:00:15 +0000</pubDate>
      <link>https://dev.to/ghostkeeper10/how-to-implement-a-global-error-handling-popup-in-react-native-with-react-query-i41</link>
      <guid>https://dev.to/ghostkeeper10/how-to-implement-a-global-error-handling-popup-in-react-native-with-react-query-i41</guid>
      <description>&lt;p&gt;Handling errors gracefully in a React Native application is essential for providing a smooth user experience. One effective approach is to implement a global error handling popup that informs users of issues and allows them to retry failed actions. In this blog post, we will walk through how to achieve this using React Native and React Query.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up Your Project
&lt;/h3&gt;

&lt;p&gt;Ensure you have a React Native project set up. If not, you can create one using &lt;a href="https://docs.expo.dev/tutorial/create-your-first-app/"&gt;Expo&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating the PopupController
&lt;/h3&gt;

&lt;p&gt;PopupController will manage the visibility of the GlobalPopup. This controller can be used by other components to show or hide the popup.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;PopupRef&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;failedQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;hide&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;PopupController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;popupRef&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MutableRefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PopupRef&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;static&lt;/span&gt; &lt;span class="nx"&gt;setGlobalPopupRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;MutableRefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PopupRef&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;popupRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;showGlobalPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;failedQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryKey&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;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;popupRef&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;show&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;failedQuery&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;hideGlobalPopup&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;popupRef&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;hide&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;
  
  
  Creating the GlobalPopup Component
&lt;/h3&gt;

&lt;p&gt;The GlobalPopup component will display error messages and provide an option to retry failed actions. It uses useLayoutEffect to set the ref of GlobalPopup in the popupController. It also uses useImperativeHandle to customise the handle exposed as a ref, allowing it to show and hide the popup.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;GlobalPopup&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;visible&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setVisible&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;failedQueries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFailedQueries&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;QueryKey&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;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQueryClient&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;popupRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useRef&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PopupRef&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;// Using useLayoutEffect to set the ref of GlobalPopup in popupController&lt;/span&gt;
  &lt;span class="nf"&gt;useLayoutEffect&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;PopupController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setGlobalPopupRef&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;popupRef&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;MutableRefObject&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;PopupRef&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;

  &lt;span class="c1"&gt;// Using useImperativeHandle to customize the handle exposed as a ref&lt;/span&gt;
  &lt;span class="nf"&gt;useImperativeHandle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;popupRef&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;show&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="na"&gt;failedQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QueryKey&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;setVisible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;failedQueries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;failedQuery&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nf"&gt;setFailedQueries&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;failedQueries&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;failedQuery&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;hide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;setVisible&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;setFailedQueries&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;failedQueries&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;handleTryAgain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;failedQueries&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&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="nx"&gt;queryClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;invalidateQueries&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;queryKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&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;PopupController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hideGlobalPopup&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="nc"&gt;Modal&lt;/span&gt; &lt;span class="na"&gt;visible&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;visible&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;View&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;Text&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;This is a global error popup&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Text&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;Button&lt;/span&gt; &lt;span class="na"&gt;onPress&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleTryAgain&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Try Again"&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;View&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;Modal&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;h3&gt;
  
  
  Integrating GlobalPopup in the App Component
&lt;/h3&gt;

&lt;p&gt;Now, integrate the GlobalPopup in the top-level component of your application and set up the React Query client to handle errors globally.&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;queryClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;QueryClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;queryCache&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;QueryCache&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="c1"&gt;// Overwriting queryClient to handle errors globally&lt;/span&gt;
    &lt;span class="na"&gt;onError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;query&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;PopupController&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;showGlobalPopup&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;queryKey&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;
  
  
  How it works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;When any component in the application makes an API call using useQuery and it fails, the configured onError handler in App.tsx is triggered.&lt;/li&gt;
&lt;li&gt;The onError handler calls PopupController.showGlobalPopup with the failed query key (e.g., ["key"]).&lt;/li&gt;
&lt;li&gt;The show function in the popup reference object updates the visibility state of GlobalPopup and adds the failed query key to the internal list. &lt;/li&gt;
&lt;li&gt;The global error popup becomes visible, displaying a generic error message and a "Try Again" button.&lt;/li&gt;
&lt;li&gt;Clicking "Try Again" triggers handleTryAgain in the popup. This function iterates through the failed queries, invalidates them using queryClient, and calls PopupController.hideGlobalPopup to hide the popup.&lt;/li&gt;
&lt;li&gt;React Query refetches the invalidated queries, potentially resolving the error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By incorporating these enhancements, you can create a robust and informative error handling experience for your React Native applications.&lt;/p&gt;

&lt;p&gt;Sample project with global error handling implementation: &lt;a href="https://github.com/rupeshghosh10/global-error-popup"&gt;github&lt;/a&gt;&lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to implement Infinite Scrolling in React Native</title>
      <dc:creator>Rupesh Ghosh</dc:creator>
      <pubDate>Wed, 01 May 2024 18:37:06 +0000</pubDate>
      <link>https://dev.to/ghostkeeper10/how-to-implement-infinite-scrolling-in-react-native-ig</link>
      <guid>https://dev.to/ghostkeeper10/how-to-implement-infinite-scrolling-in-react-native-ig</guid>
      <description>&lt;p&gt;In mobile apps, displaying large datasets efficiently is crucial. Imagine a social media feed or an e-commerce product listing, you don't want to overwhelm the user by loading everything at once. Infinite scrolling, where new content loads as the user scrolls down, provides a smooth and performant solution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting up the project
&lt;/h3&gt;

&lt;p&gt;For this blog post, we will assume you have a React Native project set up and an API endpoint that returns paginated data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Install react-query&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;npm install react-query
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React Query provides &lt;strong&gt;useInfiniteQuery&lt;/strong&gt; hook which is specifically designed for fetching and managing paginated data. You can read more about useInfiniteQuery &lt;a href="https://tanstack.com/query/v4/docs/framework/react/reference/useInfiniteQuery"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementing Infinite Scrolling with useInfiniteQuery
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Define the Query Function&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This function fetches data from the API endpoint. It should accept the current page number as a parameter and return the fetched data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fetchArticles&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="nx"&gt;page&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&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;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="s2"&gt;`http://api.example.com?page=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Using &lt;strong&gt;useInfiniteQuery&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&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;useInfiniteQuery&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-query&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;ArticleList&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="nx"&gt;hasNextPage&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useInfiniteQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;articles&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fetchArticles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;getNextPageParam&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lastPage&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;lastPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&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="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="nc"&gt;FlatList&lt;/span&gt;
      &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&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;pages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;renderItem&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="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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Article&lt;/span&gt; &lt;span class="na"&gt;article&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onEndReached&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasNextPage&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;fetchNextPage&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;ListFooterComponent&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="nx"&gt;ActivityIndicator&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
     &lt;span class="c1"&gt;// other FlatList props&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;ul&gt;
&lt;li&gt;
&lt;strong&gt;useInfiniteQuery&lt;/strong&gt; manages the fetching and caching of paginated data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;getNextPageParam&lt;/strong&gt; is crucial for pagination. It takes the last fetched page (lastPage) and determines the next page parameter for the API request. If there are no more pages, it returns undefined. Modify this function based on your API's pagination structure (e.g., page numbers).&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;isLoading&lt;/strong&gt; indicates if data is currently being fetched. You can use this to display a loading indicator while data loads. A loading indicator is displayed using &lt;strong&gt;ListFooterComponent&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;onEndReached&lt;/strong&gt; within FlatList gets called when the user scrolls close to the end of the list. It's used to trigger the loading of the next page of data. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;We can also adjust the threshold for triggering onEndReached using the &lt;strong&gt;onEndReachedThreshold&lt;/strong&gt; prop of FlatList. This value represents a fraction of the list's viewable height from the bottom For example 0.5 means triggering when the user is halfway through the last visible item.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;By leveraging useInfiniteQuery, you can effortlessly implement infinite scrolling in your React Native applications. This approach goes beyond articles – you can adapt it to various use cases like product listings, chat history, or any scenario where you're dealing with large datasets. &lt;/p&gt;

</description>
      <category>reactnative</category>
      <category>mobile</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to use Community Toolkit MVVM in Avalonia</title>
      <dc:creator>Rupesh Ghosh</dc:creator>
      <pubDate>Sun, 07 May 2023 13:11:24 +0000</pubDate>
      <link>https://dev.to/ghostkeeper10/how-to-use-community-toolkit-mvvm-in-avalonia-39af</link>
      <guid>https://dev.to/ghostkeeper10/how-to-use-community-toolkit-mvvm-in-avalonia-39af</guid>
      <description>&lt;p&gt;Avalonia is an open-source, cross-platform .NET UI framework that enables developers to create desktop applications that run on Windows, macOS, and Linux. Avalonia provides built-in support for the Model-View-ViewModel (MVVM) pattern.&lt;/p&gt;

&lt;h3&gt;
  
  
  Setting Up the Project
&lt;/h3&gt;

&lt;p&gt;Before we dive into using the MVVM Community Toolkit, we need to set up a basic Avalonia MVVM application. We can do this by creating a new project in Visual Studio or Rider and selecting the "Avalonia MVVM Application" project template, or via the .NET CLI&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;avalonia.mvvm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Sample&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-n&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Sample&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Using Community Toolkit MVVM in Avalonia
&lt;/h3&gt;

&lt;p&gt;The Community Toolkit MVVM is a lightweight, flexible, and easy-to-use MVVM framework that provides basic infrastructure for implementing MVVM in .NET applications. It is maintained and published by Microsoft and is part of the .NET Foundation.&lt;/p&gt;

&lt;p&gt;To use Community Toolkit MVVM in an Avalonia application, follow these steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the CommunityToolkit.Mvvm package from NuGet package manager or via .NET CLI
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;dotnet&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;package&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CommunityToolkit.Mvvm&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Remove Avalonia.ReactiveUI Package Reference from Sample.csproj&lt;/li&gt;
&lt;li&gt;From Program.cs, Remove &lt;code&gt;UseReactiveUI()&lt;/code&gt; extension method from BuildAvaloniaApp method.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;AppBuilder&lt;/span&gt; &lt;span class="nf"&gt;BuildAvaloniaApp&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AppBuilder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Configure&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;App&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;UsePlatformDetect&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;LogToTrace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;In ViewModels/ViewModelBase.cs, Inherit from &lt;code&gt;ObservableObject&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ViewModelBase&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ObservableObject&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;
  
  
  Comparing Community Toolkit MVVM and Reactive UI
&lt;/h3&gt;

&lt;p&gt;While both Community Toolkit MVVM and Reactive UI are popular MVVM frameworks for .NET applications, they have different strengths and weaknesses. Here are some trade-offs to consider when choosing between them:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Complexity:&lt;/strong&gt; Reactive UI is a more complex and powerful framework than Community Toolkit MVVM. While Reactive UI provides advanced features for reactive programming and asynchronous data binding, it can be more difficult to learn and use, especially for developers who are new to reactive programming.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Performance:&lt;/strong&gt; Reactive UI can be slower than Community Toolkit MVVM due to its reliance on reactive programming and the Rx library. While the performance difference may not be noticeable in small applications, it can become an issue in larger, more complex applications.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibility:&lt;/strong&gt; Reactive UI provides more flexibility and power than Community Toolkit MVVM, allowing developers to implement complex scenarios such as multi-threading, custom schedulers, and advanced data binding scenarios.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Create a Custom Progress Bar with moving percentage in WPF</title>
      <dc:creator>Rupesh Ghosh</dc:creator>
      <pubDate>Sat, 22 Apr 2023 13:23:41 +0000</pubDate>
      <link>https://dev.to/ghostkeeper10/create-a-custom-progress-bar-with-moving-percentage-in-wpf-4k7e</link>
      <guid>https://dev.to/ghostkeeper10/create-a-custom-progress-bar-with-moving-percentage-in-wpf-4k7e</guid>
      <description>&lt;h3&gt;
  
  
  Introduction
&lt;/h3&gt;

&lt;p&gt;As a dotnet developer, you may have found yourself in need of a progress bar to indicate the progress of a task. While the built in WPF progress bar is functional, it may not always fit the specific requirements of your project. In this blog post, I will show you how to create a custom progress bar with a moving percentage in WPF.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project setup
&lt;/h3&gt;

&lt;p&gt;To get started, we'll create a separate WPF user control library for our custom progress bar. This will allow us to reuse the progress bar in different projects without having to write the same code over and over again.&lt;br&gt;
Here are the steps to create a WPF user control library in Visual Studio:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Open Visual Studio and create a new project.&lt;/li&gt;
&lt;li&gt;In the New Project dialog box, select WPF User Control Library and click Next.&lt;/li&gt;
&lt;li&gt;Give your project a name and click Next.&lt;/li&gt;
&lt;li&gt;Select the dotnet version and click Create.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Designing the custom progress bar
&lt;/h3&gt;

&lt;p&gt;To create a custom progress bar with a moving percentage in WPF, we'll need to use two converters. Converters are classes that can convert one type of value to another and are used in WPF to bind UI elements to data. In this case, we'll use two converters to bind the progress bar's width to its value, and its inverse width to its remaining value (i.e 100 - value). &lt;/p&gt;

&lt;p&gt;Add below two converters the project:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ProgressBarValueToWidthConverter
```Csharp
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;internal class ProgressBarValueToWidthConverter : IValueConverter&lt;br&gt;
{&lt;br&gt;
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)&lt;br&gt;
    {&lt;br&gt;
        var progressBarValue = System.Convert.ToDouble(value);&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    if (progressBarValue &amp;gt;= 100)
    {
        return "100*";
    }

    return $"{progressBarValue}*";
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;



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


internal class InverseProgressBarValueToWidthConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var progressBar = System.Convert.ToDouble(value);

        if (progressBar &amp;gt;= 100)
        {
            return "0*";
        }

        return $"{100.0 - progressBar}*";
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


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

&lt;/div&gt;

&lt;p&gt;By using these two converters in combination, we can create a progress bar that dynamically moves the percentage value of the progress bar as the task progresses.&lt;/p&gt;

&lt;p&gt;Now, Add a new UserControl name 'CustomProgressBar' to the project.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CustomProgressBar.xaml
```html
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"&lt;br&gt;
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&lt;br&gt;
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" &lt;br&gt;
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"&lt;br&gt;
             xmlns:converters="clr-namespace:CustomProgressbar.Converters"&lt;br&gt;
             mc:Ignorable="d"&lt;br&gt;
             x:Name="CustomProgressBarUC"&amp;gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;UserControl.Resources&amp;gt;
    &amp;lt;converters:ProgressBarValueToWidthConverter x:Key="ProgressBarValueToWidthConverter" /&amp;gt;
    &amp;lt;converters:InverseProgressBarValueToWidthConverter x:Key="InverseProgressBarValueToWidthConverter" /&amp;gt;
&amp;lt;/UserControl.Resources&amp;gt;

&amp;lt;StackPanel HorizontalAlignment="Center"&amp;gt;
    &amp;lt;Grid&amp;gt;
        &amp;lt;Grid.ColumnDefinitions&amp;gt;
            &amp;lt;ColumnDefinition Width="{Binding ElementName=CustomProgressBarUC, Path=ProgressBarValue, Converter={StaticResource ProgressBarValueToWidthConverter}}" /&amp;gt;
            &amp;lt;ColumnDefinition Width="{Binding ElementName=CustomProgressBarUC, Path=ProgressBarValue, Converter={StaticResource InverseProgressBarValueToWidthConverter}}" /&amp;gt;
        &amp;lt;/Grid.ColumnDefinitions&amp;gt;
        &amp;lt;TextBlock Text="{Binding ElementName=CustomProgressBarUC, Path=ProgressBarValue, StringFormat={}{0:F0}%}"
                   FontSize="9px"
                   HorizontalAlignment="Right" /&amp;gt;
    &amp;lt;/Grid&amp;gt;
    &amp;lt;ProgressBar Minimum="0"
                 Value="{Binding ElementName=CustomProgressBarUC, Path=ProgressBarValue, Mode=OneWay}"
                 Maximum="100"
                 Height="8"
                 Width="300"
                 Foreground="DarkBlue"
                 Background="LightGray"
                 BorderBrush="LightGray" /&amp;gt;
&amp;lt;/StackPanel&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;In the above XAML file, we have 'StackPanel' to hold our progress bar and percentage text. Inside the 'StackPanel', we'll have a 'Grid' to hold the progress bar. 

We've added two column definitions to the 'Grid'. The first column's width is bound to the 'ProgressBarValue' property of our user control, and we've used the 'ProgressBarValueToWidthConverter' converter to convert the progress bar value to a width. The second column's width is also bound to the 'ProgressBarValue; property, but we've used the 'InverseProgressBarValueToWidthConverter' converter to convert the inverse value of the progress bar to a width.

We've also added a 'TextBlock' to show the progress percentage. Its 'Text' property is bound to the 'ProgressBarValue' property, and we've used a 'StringFormat' to display the value as a percentage with no decimal places.

Finally, we'll add a 'ProgressBar' control to the 'StackPanel'. We'll bind its Value property to the 'ProgressBarValue' property of our user control, and we'll set its Minimum and Maximum values to 0 and 100, respectively.

- CustomProgressBar.xaml.cs

```Csharp


public partial class Progressbar : UserControl
{
    public Progressbar()
    {
        InitializeComponent();
        ProgressBarValue = 0;
    }

    public double ProgressBarValue
    {
        get =&amp;gt; (double)GetValue(ProgressBarValueProperty);
        set =&amp;gt; SetValue(ProgressBarValueProperty, value);
    }

    // Using a DependencyProperty as the backing store for ProgressBarValue.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ProgressBarValueProperty =
        DependencyProperty.Register(nameof(ProgressBarValue), typeof(double), typeof(Progressbar));
}


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

&lt;/div&gt;

&lt;p&gt;The above CustomProgressBar has a public property called 'ProgressBarValue' which is backed by a DependencyProperty. This property allows the value of the progress bar to be set and updated from the main project. &lt;/p&gt;

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

&lt;p&gt;With these elements in place, we can create a fully functional custom progress bar with a moving percentage in WPF, simply by using the UserControl that contains the progress bar, as a separate library in our main project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fumfvi1pfly2cxh1bg9f9.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%2Fuploads%2Farticles%2Fumfvi1pfly2cxh1bg9f9.gif" alt="Progress Bar"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Source Code: &lt;a href="https://github.com/RupeshGhosh10/CustomProgressBar" rel="noopener noreferrer"&gt;https://github.com/RupeshGhosh10/CustomProgressBar&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
