<?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: Max Abrams</title>
    <description>The latest articles on DEV Community by Max Abrams (@maxabrams).</description>
    <link>https://dev.to/maxabrams</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%2F779763%2Fd576286f-e03c-474e-879c-c2c59da5ee7b.jpeg</url>
      <title>DEV Community: Max Abrams</title>
      <link>https://dev.to/maxabrams</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/maxabrams"/>
    <language>en</language>
    <item>
      <title>Generate React-Router routes for your components automatically with MacroLock and Screen-Schemas</title>
      <dc:creator>Max Abrams</dc:creator>
      <pubDate>Sun, 10 Sep 2023 15:47:35 +0000</pubDate>
      <link>https://dev.to/maxabrams/generate-react-router-routes-for-your-components-automatically-with-macrolock-and-screen-schemas-4og4</link>
      <guid>https://dev.to/maxabrams/generate-react-router-routes-for-your-components-automatically-with-macrolock-and-screen-schemas-4og4</guid>
      <description>&lt;p&gt;Hello, fellow developers! Today, I want to share with you two fantastic NPM modules that have been game-changers in my React projects. They’re called &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt;, and they’ve made my development process smoother, faster, and more efficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sHUPi0N_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:700/1%2AVoZ0ZIWrZqKfVSH6Lzhlvg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sHUPi0N_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://miro.medium.com/v2/resize:fit:700/1%2AVoZ0ZIWrZqKfVSH6Lzhlvg.png" alt="screenConfig example" width="700" height="422"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Birth of MacroLock and Screen-Schemas
&lt;/h2&gt;

&lt;p&gt;These two modules were born out of necessity while working on a project where I needed to automatically generate routes for the react router for all my screen components. After solving this problem, I thought it would be great to turn them into NPM modules so others could benefit too.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are MacroLock and Screen-Schemas?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; is a utility tool that helps you detect changes in a directory and execute a script if changes are detected. It does this by generating a checksum for the directory and comparing it with a previously stored checksum. If the checksums do not match, it means there have been changes in the directory, and &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; will execute the provided script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt;, on the other hand, is designed to generate screen descriptions from a directory of screen components for routes and navigation. It scans a directory for .tsx files, extracts configuration from comments in the files, and outputs a JSON file.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do They Work Together?
&lt;/h2&gt;

&lt;p&gt;In my project setup, I use these two modules in tandem with chokidar (a file watcher) to automate route generation based on my screen components. Here’s how it works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Chokidar watches for any file changes in my screens directory.&lt;/li&gt;
&lt;li&gt;When changes are detected, &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; checks if there have been any substantial changes (i.e., changes that affect the checksum).&lt;/li&gt;
&lt;li&gt;However, MacroLock isn’t just a passive observer waiting for Chokidar to detect changes. It’s an active participant in the process, capable of running change detection whenever you like without dependence on an active watcher.&lt;/li&gt;
&lt;li&gt;This means that even when there isn’t an active watcher, MacroLock can still detect changes made against a previously recorded checksum.&lt;/li&gt;
&lt;li&gt;If there have been substantial changes, &lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt; is triggered to scan all .tsx files in the screens directory.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt; then generates a routes.json file based on the configuration provided in the comments of each .tsx file.&lt;/li&gt;
&lt;li&gt;This routes.json file is then used to dynamically generate routes in my React app.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;This setup ensures that no change goes unnoticed and your routes are always up-to-date, regardless of whether there’s an active watcher or not.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Here’s a snippet from my package.json showing how I’ve set up these scripts:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;scripts:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="nl"&gt;"generate-routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn screen-schemas './src/components/screens/*.tsx' './src/routes.json'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="nl"&gt;"ifDif:buildroutes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"yarn macrolock ./src/components/screens ./locks/routes.lock 'yarn generate-routes'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="nl"&gt;"watch:routes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"chokidar './src/components/screens/' -c 'yarn ifDif:buildroutes'"&lt;/span&gt;&lt;span class="w"&gt;  
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here’s how I use the generated routes.json in my React app:&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="nx"&gt;routesJson&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;../../routes.json&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  
&lt;span class="c1"&gt;// Create a map with all components in the @self directory  &lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;components&lt;/span&gt; &lt;span class="o"&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;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/src/components/screens/*.tsx&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;function&lt;/span&gt; &lt;span class="nx"&gt;RouterProvider&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useTranslation&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;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routesJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;route&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;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lazy&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="nx"&gt;components&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;  
     &lt;span class="s2"&gt;`/src/components/screens/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tsx`&lt;/span&gt;  
       &lt;span class="p"&gt;]()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;  
         &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ComponentType&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&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="o"&gt;&amp;gt;&lt;/span&gt;  
     &lt;span class="p"&gt;);&lt;/span&gt;  
     &lt;span class="c1"&gt;// … rest of the code  &lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;  
   &lt;span class="c1"&gt;// … rest of the code  &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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;  
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;  
          &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  
          &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&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;PageWrapper&lt;/span&gt;  
              &lt;span class="na"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="si"&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;route&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;  
              &lt;span class="na"&gt;hideBackButton&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;hasOwn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;onBackClick&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="p"&gt;&amp;gt;&lt;/span&gt;  
              &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;component&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;PageWrapper&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;span class="p"&gt;}),&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;ReactRouterProvider&lt;/span&gt; &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Integrating MacroLock in CI/CD Workflows
&lt;/h2&gt;

&lt;p&gt;One of the powerful features of &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; is its ability to be integrated into your Continuous Integration and Continuous Deployment (CI/CD) workflows.&lt;/p&gt;

&lt;p&gt;Thanks to the recorded lock file, &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; can be run as part of your CI/CD pipeline. This means that every time you push changes to your repository or deploy your application, &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; can automatically check for changes and execute necessary scripts if any changes are detected.&lt;/p&gt;

&lt;p&gt;This feature ensures that your routes are always up-to-date and consistent with your screen components, even across different environments and deployment stages. It also eliminates the need for manual intervention in updating routes during the deployment process, making your deployments smoother and more reliable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Should You Use Them?
&lt;/h2&gt;

&lt;p&gt;The beauty of this setup is that it automates a process that would otherwise be manual and prone to errors. It ensures that every time you add, remove, or modify a screen component, your routes are automatically updated to reflect these changes. This not only saves you time but also ensures consistency and accuracy in your routing.&lt;/p&gt;

&lt;p&gt;Moreover, &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; isn’t limited to just working with &lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt;. You can use it to monitor any directory and execute any script when changes are detected. In my project, I also use it for generating barrel files and building Python scripts. This flexibility makes MacroLock a versatile tool that can be adapted for various use cases in your project.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping Up
&lt;/h2&gt;

&lt;p&gt;In conclusion, &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt; are powerful tools that can significantly enhance your React development process. They’re easy to install, simple to use, and highly customizable to suit your specific needs.&lt;/p&gt;

&lt;p&gt;So why not give them a try? They might just become your new favorite tools in your developer toolkit!&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributing and Licensing
&lt;/h2&gt;

&lt;p&gt;Both &lt;a href="https://www.npmjs.com/package/macrolock"&gt;MacroLock&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/screen-schemas"&gt;Screen-Schemas&lt;/a&gt; are open-source projects hosted on GitHub &lt;a href="https://github.com/maxabrahamsson/macrolock"&gt;MacroLock Repository&lt;/a&gt;, &lt;a href="https://github.com/maxabrahamsson/screen-schemas"&gt;Screen-Schemas Repository&lt;/a&gt;. Contributions in the form of issues, pull requests, or feedback are always welcome!&lt;/p&gt;

&lt;p&gt;For licensing details, please refer to the respective repositories.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

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