<?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: Prazin Karki</title>
    <description>The latest articles on DEV Community by Prazin Karki (@pktechie).</description>
    <link>https://dev.to/pktechie</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F317055%2F6baedb65-ebb0-4a0c-bb34-6943a0511370.jpg</url>
      <title>DEV Community: Prazin Karki</title>
      <link>https://dev.to/pktechie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pktechie"/>
    <language>en</language>
    <item>
      <title>What Building Pagelyze Taught Me About React Best Practices</title>
      <dc:creator>Prazin Karki</dc:creator>
      <pubDate>Fri, 26 Jun 2026 11:37:58 +0000</pubDate>
      <link>https://dev.to/pktechie/what-building-pagelyze-taught-me-about-react-best-practices-5fhb</link>
      <guid>https://dev.to/pktechie/what-building-pagelyze-taught-me-about-react-best-practices-5fhb</guid>
      <description>&lt;p&gt;What building Pagelyze taught me about React best practices - and why it has very little to do with hooks.&lt;/p&gt;

&lt;p&gt;Building Pagelyze has made me think more carefully about React best practices, not as theory, but as product architecture.&lt;/p&gt;

&lt;p&gt;I already work across Vue, Nuxt, Laravel, CMS platforms, and analytics. But React is a skill I want to sharpen properly, especially while building my own product, &lt;strong&gt;&lt;a href="https://pagelyze.pktechie.com.au/" rel="noopener noreferrer"&gt;Pagelyze&lt;/a&gt;&lt;/strong&gt; (a website audit and lead-check tool), under &lt;strong&gt;&lt;a href="https://pktechie.com.au/" rel="noopener noreferrer"&gt;PKTechie&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Pagelyze isn't a toy app with a few components. It has real product concerns: audit reports, scoring logic, lead-flow evidence, dashboards, and paid-conversion paths. So while relearning React, I kept asking one practical question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Can the code stay clean while the product gets more useful?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Good React isn't just about hooks
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, &lt;code&gt;useMemo&lt;/code&gt;, custom hooks - important, but not the full story. A React app can use modern syntax everywhere and still be miserable to maintain. The real issue is rarely syntax. It's whether each piece of code has a &lt;em&gt;clear responsibility&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Component responsibility matters early
&lt;/h2&gt;

&lt;p&gt;In Pagelyze, an audit report screen could easily turn into one giant file handling everything from loading data to deciding which service to recommend. It would work for a while - it wouldn't scale.&lt;/p&gt;

&lt;p&gt;A cleaner split:&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="nc"&gt;AuditSummary&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;LeadCheckPanel&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;EvidenceList&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;ServiceRecommendationCard&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;ReportActions&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;Each component has one clear reason to exist - so I can improve Lead Rescue without touching SEO scoring, or redesign a card without rewriting data logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  State should live where it makes sense
&lt;/h2&gt;

&lt;p&gt;The better question isn't "Redux or Context?" - it's &lt;strong&gt;who actually needs this state?&lt;/strong&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="nx"&gt;Local&lt;/span&gt; &lt;span class="nx"&gt;UI&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="nx"&gt;tabs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;toggles&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;modals&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expanded&lt;/span&gt; &lt;span class="nx"&gt;panels&lt;/span&gt;
&lt;span class="nx"&gt;Form&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="nx"&gt;audit&lt;/span&gt; &lt;span class="nx"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;validation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;submission&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt;
&lt;span class="nx"&gt;Server&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="nx"&gt;audit&lt;/span&gt; &lt;span class="nx"&gt;reports&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scans&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;saved&lt;/span&gt; &lt;span class="nx"&gt;results&lt;/span&gt;
&lt;span class="nx"&gt;Global&lt;/span&gt; &lt;span class="nx"&gt;state&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;organisation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;permissions&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Hooks should extract meaning, not hide mess
&lt;/h2&gt;

&lt;p&gt;A custom hook should represent a meaningful piece of behaviour, not just relocate messy code:&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;report&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;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuditReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;AuditReportPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;reportId&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;reportId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;report&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;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useAuditReport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reportId&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;isLoading&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReportLoadingState&lt;/span&gt; &lt;span class="p"&gt;/&amp;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;error&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReportErrorState&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;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ReportLayout&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;AuditSummary&lt;/span&gt; &lt;span class="na"&gt;report&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;report&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;LeadCheckPanel&lt;/span&gt; &lt;span class="na"&gt;leadCheck&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;leadCheck&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;RecommendedFixes&lt;/span&gt; &lt;span class="na"&gt;report&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;report&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;ReportLayout&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;The page only coordinates the screen - that's enough.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structure the project around the product, not the framework
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;features&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;audit&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;report&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ts&lt;/span&gt;
  &lt;span class="nx"&gt;lead&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;rescue&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;evidence&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;manual&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;proof&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
  &lt;span class="nx"&gt;dashboard&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;components&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
    &lt;span class="nx"&gt;hooks&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Routing is part of conversion
&lt;/h2&gt;

&lt;p&gt;For Pagelyze, routing is not just URLs. It is the user journey from the first landing page visit to a clear service enquiry:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Landing page
  ↓
Free audit
  ↓
Report result
  ↓
Lead-check explanation
  ↓
Recommended fix
  ↓
Service enquiry
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good routing guides them to the next step.&lt;/p&gt;

&lt;h2&gt;
  
  
  Measure performance - don't guess it
&lt;/h2&gt;

&lt;p&gt;Build clearly. Measure honestly. Find the actual bottleneck. Optimise that specific thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security is front-end work too
&lt;/h2&gt;

&lt;p&gt;The rule I keep coming back to: &lt;strong&gt;don't expose anything in the browser that shouldn't be public.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The takeaway
&lt;/h2&gt;

&lt;p&gt;React best practices are really about decision-making - what each component owns, where state lives, whether a route helps the user move forward, and whether the app is safe and fast in real use.&lt;/p&gt;

&lt;p&gt;Pagelyze is my real test: not whether I can build a screen, but whether I can keep the product clean and maintainable as it gets more serious.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://pktechie.com.au/blog/react-best-practices-real-saas-product" rel="noopener noreferrer"&gt;PKTechie&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

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