<?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: Nikhil Sharma</title>
    <description>The latest articles on DEV Community by Nikhil Sharma (@nikhilsharma6).</description>
    <link>https://dev.to/nikhilsharma6</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%2F3222504%2F0c35495e-0c52-43f3-a92d-07854e3cd0e0.jpg</url>
      <title>DEV Community: Nikhil Sharma</title>
      <link>https://dev.to/nikhilsharma6</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nikhilsharma6"/>
    <language>en</language>
    <item>
      <title>The WebSocket Auth Problem: Cookies vs. Bearer Tokens</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Wed, 03 Jun 2026 20:23:14 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/the-websocket-auth-problem-cookies-vs-bearer-tokens-4eel</link>
      <guid>https://dev.to/nikhilsharma6/the-websocket-auth-problem-cookies-vs-bearer-tokens-4eel</guid>
      <description>&lt;p&gt;If you've ever built a real-time web app using WebSockets, you've probably hit this exact wall - how do I do the auth.&lt;/p&gt;

&lt;p&gt;On the HTTP side, the answer is pretty simple. You either use a cookie, which has so many npm packages, or you attach an &lt;code&gt;Authorization: Bearer &amp;lt;token&amp;gt;&lt;/code&gt; header to your requests, which is a simple JWT signed string. However, things get a bit weird on the WebSocket side of things.&lt;/p&gt;

&lt;p&gt;The fundamental issue stems from how WebSocket connections are established. Before a WebSocket connection becomes a continuous bidirectional channel of data, it starts off as a simple HTTP &lt;code&gt;GET&lt;/code&gt; request with an &lt;code&gt;Upgrade&lt;/code&gt; header. This is known as the WebSocket Handshake.&lt;/p&gt;

&lt;p&gt;Let's dive into why this handshake makes the seemingly simple task of authentication a surprisingly nuanced architectural decision.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Bearer Tokens are Clunky for WebSockets
&lt;/h2&gt;

&lt;p&gt;If your application relies on Bearer tokens (usually stored in memory or local storage on the client side), you are used to attaching them via the &lt;code&gt;Authorization&lt;/code&gt; header using an interceptor or a fetch wrapper.&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="c1"&gt;// A typical HTTP request with a Bearer token&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/data&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;headers&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;Authorization&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;myToken&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the native browser &lt;code&gt;WebSocket&lt;/code&gt; API &lt;strong&gt;does not support custom headers&lt;/strong&gt;.&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="c1"&gt;// This is all we get.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&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;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://api.myapp.com/socket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Since you can't pass the token in an &lt;code&gt;Authorization&lt;/code&gt; header during the initial HTTP Upgrade request, developers are forced into clunky workarounds:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Query Parameters&lt;/strong&gt;: Passing the token in the URL (&lt;code&gt;wss://api.myapp.com/socket?token=ey...&lt;/code&gt;). This is generally considered a bad practice because URLs (and the sensitive tokens within them) end up in server logs, browser histories, and proxy logs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;First Message Auth&lt;/strong&gt;: Opening the WebSocket connection unauthenticated, and then requiring the client to immediately send an authentication message containing the token before the server accepts any further messages. While secure, this adds latency and complexity to the connection lifecycle logic. You have to write boilerplate to handle connections that open but never authenticate.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subprotocols&lt;/strong&gt;: A hacky but working method where the token is passed as a WebSocket subprotocol (&lt;code&gt;new WebSocket('wss://...', ['access_token', token])&lt;/code&gt;).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;None of these feel particularly clean or idiomatic.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Cookies Work Naturally
&lt;/h2&gt;

&lt;p&gt;This brings us to cookies, the method that I chose for &lt;a href="https://github.com/nikshrma/relay" rel="noopener noreferrer"&gt;Relay&lt;/a&gt;! Cookies are managed by the browser. Whenever the browser makes an HTTP request to a domain, it automatically attaches the cookies associated with that domain.&lt;/p&gt;

&lt;p&gt;Because the WebSocket handshake is just a standard HTTP &lt;code&gt;GET&lt;/code&gt; request, &lt;strong&gt;the browser automatically includes your cookies&lt;/strong&gt; in the first request itself!&lt;/p&gt;

&lt;p&gt;If your authentication system sets an HTTP-only cookie containing your JWT or session ID when the user logs in, you literally don't have to change any client-side code to authenticate your WebSockets. The browser handles it natively and securely.&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="c1"&gt;// The browser automatically attaches the JWT auth cookie!&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ws&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;WebSocket&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;wss://api.myapp.com/socket&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Backend Implementation: Parsing the Cookie
&lt;/h2&gt;

&lt;p&gt;While the client side becomes trivial, the backend need manual cookie parsing. When your WebSocket server receives the &lt;code&gt;upgrade&lt;/code&gt; request, it hands you a raw Node.js &lt;code&gt;IncomingMessage&lt;/code&gt; object. &lt;/p&gt;

&lt;p&gt;Unlike Express requests which come with the &lt;code&gt;cookies&lt;/code&gt; objects provided by middleware, the &lt;code&gt;IncomingMessage&lt;/code&gt; just gives you the raw &lt;code&gt;cookie&lt;/code&gt; header string. You have to parse it yourself before accepting the WebSocket connection.&lt;/p&gt;

&lt;p&gt;Below is how I did the cookie parsing in Relay!&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Extracting and Verifying the Token
&lt;/h3&gt;

&lt;p&gt;First, we need a utility function to take the raw &lt;code&gt;IncomingMessage&lt;/code&gt;, parse the cookie string, and verify our JWT.&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;import&lt;/span&gt; &lt;span class="nx"&gt;cookie&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;cookie&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="nx"&gt;jwt&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;jsonwebtoken&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;IncomingMessage&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;http&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;jwtPayloadSchema&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;../../http/schemas/auth.schema.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Extract user ID from the raw HTTP upgrade request&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;extractUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IncomingMessage&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Parse the raw cookie header string&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cookie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="nx"&gt;cookie&lt;/span&gt; &lt;span class="o"&gt;??&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;token&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cookies&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;token&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;token&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&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="c1"&gt;// Verify the JWT signature&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;decoded&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;verify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;token&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;JWT_SECRET&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Validate the payload shape&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;jwtPayloadSchema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;safeParse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;decoded&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;parsed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&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="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Return the authenticated User ID&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;parsed&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;id&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="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Token is invalid or expired&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;
  
  
  2. The main Socket handling code
&lt;/h3&gt;

&lt;p&gt;Now here, I integrate this utility into my WebSocket server initialisation. I intercept the connection, attempt to extract the user ID, and immediately close the connection with a &lt;code&gt;4001 Unauthorized&lt;/code&gt; status if the authentication fails.&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;WebSocketServer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&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;ws&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="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Server&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;HttpServer&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;http&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;extractUserId&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;./handlers/message.handler.js&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;sockets&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;./store.js&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="nf"&gt;initWebSocketServer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpServer&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;wss&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;WebSocketServer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="nx"&gt;wss&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connection&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="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;WebSocket&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;IncomingMessage&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;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;error&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;console&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="c1"&gt;// 1. Authenticate immediately using the parsed cookie&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;extractUserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// 2. Reject unauthenticated connections at the handshake level&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;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4001&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Unauthorized&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="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// 3. Connection is fully authenticated!&lt;/span&gt;
    &lt;span class="c1"&gt;// We can safely associate this socket with the user&lt;/span&gt;
    &lt;span class="nx"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addUser&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;ws&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// Proceed with authorized application logic...&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`User &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; connected successfully.`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&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;data&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;// ... handle incoming messages knowing the sender's true identity&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;ws&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;close&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;sockets&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeUserSocket&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;ws&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;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;When building real-time applications, relying on HTTP-only cookies for authentication eliminates the friction of securing WebSockets. By leaning on the browser's native cookie management, we avoid leaking tokens in URLs and bypass the complexity of first-message authentication handshakes. It requires a tiny bit of manual header parsing on the backend, but the resulting client-side simplicity and security posture are well worth the trade-off.&lt;/p&gt;

&lt;p&gt;For those of you who would like to go through the codebase, you can do so here.&lt;br&gt;
I'll be back with more next week. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>I Built a Real-Time Chat App from scratch - Here's What I Learned</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Tue, 26 May 2026 18:03:37 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/i-built-a-real-time-chat-app-from-scratch-heres-what-i-learned-2nhn</link>
      <guid>https://dev.to/nikhilsharma6/i-built-a-real-time-chat-app-from-scratch-heres-what-i-learned-2nhn</guid>
      <description>&lt;p&gt;When dealing with WebSockets, most tutorials will straightaway hand you Socket.io and call it a day. You get a working chat app in short period of time but you have no idea what happened.&lt;/p&gt;

&lt;p&gt;I actually wanted to understand what was going on, how WebSockets work, how auth happens, how to deal with cookies when working with WebSockets and so many more tiny things.&lt;br&gt;
So I built Relay. A full stack real-time chat app with raw WebSockets, Express for the backend, React for the frontend and PostgreSQL. &lt;br&gt;
The reason for doing everything manually was that I wanted to &lt;strong&gt;learn&lt;/strong&gt;. I did not want to launch and make a chat app and sell it. I just wanted to learn the implementation of these technologies.&lt;/p&gt;

&lt;p&gt;Thus, here we are. This is the first post in a series where I will be exploring the project and breaking down the most interesting technical problems I ran into. But first, let's see what Relay is, how it works, and why I built it the way I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Relay Does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time messaging&lt;/strong&gt; — Messages are sent and received instantly over WebSockets. No polling, no long-polling, no hacks. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent history&lt;/strong&gt; — Every message is stored in PostgreSQL via Prisma ORM. Close the tab, logout, the messages will still be there when you come back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie-based auth&lt;/strong&gt; — JWT tokens stored in httpOnly cookies. The WebSocket handshake authenticates by manually parsing cookies from the upgrade request headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual-protocol architecture&lt;/strong&gt; — REST API(the express part) handles the CRUD stuff (auth, fetching users, loading message history). WebSockets handle the real-time stuff (sending messages, live delivery). Each protocol does what it's good at and that is exactly what I wanted to learn to do myself. And also the fact that how would I implement both these protocols in the same project for maximum efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture and Flow
&lt;/h2&gt;

&lt;p&gt;The app follows a fairly standard real-time chat architecture with a clear separation between frontend and backend responsibilities.&lt;/p&gt;

&lt;p&gt;On the frontend, the application is built using React, TypeScript, and Vite. Authentication state is managed through an AuthContext, chat history is handled using a useMessages hook, and real-time communication is managed by a useWebSocket hook. The frontend communicates with the backend in two ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST API&lt;/strong&gt; calls using &lt;strong&gt;Axios&lt;/strong&gt; over HTTP for things like authentication, fetching users, loading messages, and logout.&lt;br&gt;
&lt;strong&gt;WebSocket connections&lt;/strong&gt; (ws://) for real-time messaging and live updates.&lt;/p&gt;

&lt;p&gt;On the backend, the application uses Node.js with Express for REST APIs and the ws library for WebSocket support. The backend exposes REST routes such as /signup, /signin, /users, /messages, /me, and /logout. Alongside this, a WebSocket server handles persistent connections, live message delivery, and connection management.&lt;/p&gt;

&lt;p&gt;Both the REST API layer and WebSocket server interact with the database through Prisma ORM, which connects to a PostgreSQL database for storing users, messages, authentication data, and related application state.&lt;/p&gt;

&lt;p&gt;Now for &lt;strong&gt;the flow&lt;/strong&gt;. This is the part I find most interesting. Here's what happens when you hit send:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt; calls &lt;code&gt;sendMessage(to, content)&lt;/code&gt; which writes a JSON frame to the open WebSocket: &lt;code&gt;{ type: "send_message", payload: { to, content } }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend WS handler&lt;/strong&gt; receives it, validates the payload, and does two things simultaneously:

&lt;ul&gt;
&lt;li&gt;Persists the message to PostgreSQL via Prisma&lt;/li&gt;
&lt;li&gt;Looks up the recipient's socket in the in-memory connection store (which I will update to be a singleton SocketManager class instead of just a map)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the recipient is online, the backend &lt;strong&gt;pushes&lt;/strong&gt; the message to their socket as a &lt;code&gt;receive_message&lt;/code&gt; event, they see it instantly&lt;/li&gt;
&lt;li&gt;If they're offline, the message is still in the database. Next time they open the chat, the frontend fetches history via the REST endpoint &lt;code&gt;/messages?userId=...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The sender gets an &lt;code&gt;ack&lt;/code&gt; back over the WebSocket confirming the message was processed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No message broker, no queue, no Redis (yet, as that is the plan for v2). Just an in-memory &lt;code&gt;Map&amp;lt;userId, WebSocket&amp;gt;&lt;/code&gt; and a database. It's simple, it works for a single server, and it's the kind of thing that makes you appreciate what a system like Kafka(v2.5 maybe?) is actually solving when you eventually need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here are the interesting bits
&lt;/h2&gt;

&lt;p&gt;All of these will be individual posts in the coming days.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cookie auth over WebSockets
&lt;/h3&gt;

&lt;p&gt;Auth over REST is easy, but how does it happen when dealing with persistent connections. WebSockets don't have a middleware chain and also have no authorization header during the upgrade handshake.&lt;br&gt;
The solution - &lt;strong&gt;cookies!&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The React Stale Closure bug
&lt;/h3&gt;

&lt;p&gt;Imagine opening a chat in two tabs, you receive a message from User A, but see it silently render in the chat window for User B. No backend errors, just a complete UI mismatch.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The dual protocol magic
&lt;/h3&gt;

&lt;p&gt;How the HTTP and WS protocols interleave.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Raw WS
&lt;/h3&gt;

&lt;p&gt;How you create every feature you need using raw WebSockets instead of  Socket.io and have so much more understanding of the concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;For those of you who would like to go through the codebase, you can do so &lt;a href="https://github.com/nikshrma/relay" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;br&gt;
I'll be back with more next week. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>I Built a Real-Time Chat App from scratch - Here's What I Learned</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Tue, 26 May 2026 18:03:37 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/i-built-a-real-time-chat-app-from-scratch-heres-what-i-learned-30dd</link>
      <guid>https://dev.to/nikhilsharma6/i-built-a-real-time-chat-app-from-scratch-heres-what-i-learned-30dd</guid>
      <description>&lt;p&gt;When dealing with WebSockets, most tutorials will straightaway hand you Socket.io and call it a day. You get a working chat app in short period of time but you have no idea what happened.&lt;/p&gt;

&lt;p&gt;I actually wanted to understand what was going on, how WebSockets work, how auth happens, how to deal with cookies when working with WebSockets and so many more tiny things.&lt;br&gt;
So I built Relay. A full stack real-time chat app with raw WebSockets, Express for the backend, React for the frontend and PostgreSQL. &lt;br&gt;
The reason for doing everything manually was that I wanted to &lt;strong&gt;learn&lt;/strong&gt;. I did not want to launch and make a chat app and sell it. I just wanted to learn the implementation of these technologies.&lt;/p&gt;

&lt;p&gt;Thus, here we are. This is the first post in a series where I will be exploring the project and breaking down the most interesting technical problems I ran into. But first, let's see what Relay is, how it works, and why I built it the way I did.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Relay Does
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Real-time messaging&lt;/strong&gt; — Messages are sent and received instantly over WebSockets. No polling, no long-polling, no hacks. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Persistent history&lt;/strong&gt; — Every message is stored in PostgreSQL via Prisma ORM. Close the tab, logout, the messages will still be there when you come back.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cookie-based auth&lt;/strong&gt; — JWT tokens stored in httpOnly cookies. The WebSocket handshake authenticates by manually parsing cookies from the upgrade request headers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dual-protocol architecture&lt;/strong&gt; — REST API(the express part) handles the CRUD stuff (auth, fetching users, loading message history). WebSockets handle the real-time stuff (sending messages, live delivery). Each protocol does what it's good at and that is exactly what I wanted to learn to do myself. And also the fact that how would I implement both these protocols in the same project for maximum efficiency.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Architecture and Flow
&lt;/h2&gt;

&lt;p&gt;The app follows a fairly standard real-time chat architecture with a clear separation between frontend and backend responsibilities.&lt;/p&gt;

&lt;p&gt;On the frontend, the application is built using React, TypeScript, and Vite. Authentication state is managed through an AuthContext, chat history is handled using a useMessages hook, and real-time communication is managed by a useWebSocket hook. The frontend communicates with the backend in two ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;REST API&lt;/strong&gt; calls using &lt;strong&gt;Axios&lt;/strong&gt; over HTTP for things like authentication, fetching users, loading messages, and logout.&lt;br&gt;
&lt;strong&gt;WebSocket connections&lt;/strong&gt; (ws://) for real-time messaging and live updates.&lt;/p&gt;

&lt;p&gt;On the backend, the application uses Node.js with Express for REST APIs and the ws library for WebSocket support. The backend exposes REST routes such as /signup, /signin, /users, /messages, /me, and /logout. Alongside this, a WebSocket server handles persistent connections, live message delivery, and connection management.&lt;/p&gt;

&lt;p&gt;Both the REST API layer and WebSocket server interact with the database through Prisma ORM, which connects to a PostgreSQL database for storing users, messages, authentication data, and related application state.&lt;/p&gt;

&lt;p&gt;Now for &lt;strong&gt;the flow&lt;/strong&gt;. This is the part I find most interesting. Here's what happens when you hit send:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt; calls &lt;code&gt;sendMessage(to, content)&lt;/code&gt; which writes a JSON frame to the open WebSocket: &lt;code&gt;{ type: "send_message", payload: { to, content } }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backend WS handler&lt;/strong&gt; receives it, validates the payload, and does two things simultaneously:

&lt;ul&gt;
&lt;li&gt;Persists the message to PostgreSQL via Prisma&lt;/li&gt;
&lt;li&gt;Looks up the recipient's socket in the in-memory connection store (which I will update to be a singleton SocketManager class instead of just a map)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;If the recipient is online, the backend &lt;strong&gt;pushes&lt;/strong&gt; the message to their socket as a &lt;code&gt;receive_message&lt;/code&gt; event, they see it instantly&lt;/li&gt;
&lt;li&gt;If they're offline, the message is still in the database. Next time they open the chat, the frontend fetches history via the REST endpoint &lt;code&gt;/messages?userId=...&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The sender gets an &lt;code&gt;ack&lt;/code&gt; back over the WebSocket confirming the message was processed&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;No message broker, no queue, no Redis (yet, as that is the plan for v2). Just an in-memory &lt;code&gt;Map&amp;lt;userId, WebSocket&amp;gt;&lt;/code&gt; and a database. It's simple, it works for a single server, and it's the kind of thing that makes you appreciate what a system like Kafka(v2.5 maybe?) is actually solving when you eventually need it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Here are the interesting bits
&lt;/h2&gt;

&lt;p&gt;All of these will be individual posts in the coming days.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Cookie auth over WebSockets
&lt;/h3&gt;

&lt;p&gt;Auth over REST is easy, but how does it happen when dealing with persistent connections. WebSockets don't have a middleware chain and also have no authorization header during the upgrade handshake.&lt;br&gt;
The solution - &lt;strong&gt;cookies!&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. The React Stale Closure bug
&lt;/h3&gt;

&lt;p&gt;Imagine opening a chat in two tabs, you receive a message from User A, but see it silently render in the chat window for User B. No backend errors, just a complete UI mismatch.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. The dual protocol magic
&lt;/h3&gt;

&lt;p&gt;How the HTTP and WS protocols interleave.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Raw WS
&lt;/h3&gt;

&lt;p&gt;How you create every feature you need using raw WebSockets instead of  Socket.io and have so much more understanding of the concepts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;For those of you who would like to go through the codebase, you can do so &lt;a href="https://github.com/nikshrma/relay" rel="noopener noreferrer"&gt;here&lt;/a&gt;. &lt;br&gt;
I'll be back with more next week. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Week 12: Typescript Magic!</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Sun, 01 Feb 2026 17:11:40 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-11-typescript-magic-nmk</link>
      <guid>https://dev.to/nikhilsharma6/week-11-typescript-magic-nmk</guid>
      <description>&lt;p&gt;Last week, we talked about how Prisma helps us in simplifying our DB queries, but as a project grows, we face another massive challenge: &lt;strong&gt;consistency&lt;/strong&gt;. When you have dozens of files and data moving between them, it's very easy to lose track of what "shape" an object has. &lt;/p&gt;

&lt;p&gt;In plain JavaScript, you might call a property user_id in your database logic, userId in your controller, and just id in your frontend. In a small project, you can keep that in your head. In a production-level app? &lt;/p&gt;

&lt;p&gt;It’s a straight-up disaster waiting to happen. You won't know something is broken until the code actually runs and crashes with the dreaded Cannot read property 'id' of undefined. &lt;/p&gt;

&lt;p&gt;The solution is &lt;strong&gt;TypeScript&lt;/strong&gt;. It’s not just "JavaScript with types"; it’s a high-tech safety net. It creates a development environment where the editor itself understands your data structures. It ensures that if you change a property name in one place, the rest of your app doesn't quietly crumble—it screams at you until you fix it.&lt;/p&gt;

&lt;h3&gt;
  
  
  1a. Setting Up the Environment📎
&lt;/h3&gt;

&lt;p&gt;Unlike JavaScript, which Node.js or a browser can read directly, TypeScript needs to be "transpiled." Think of it as a pre-processing step where your type-heavy TS code is stripped down into clean, performant JS that engines can actually execute. To get started, the setup involves a few key commands that I now have on muscle memory:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Initialize a node project to manage dependencies&lt;/span&gt;
npm init &lt;span class="nt"&gt;-y&lt;/span&gt;

&lt;span class="c"&gt;# Install TypeScript as a dev dependency (we don't need it in production)&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;typescript &lt;span class="nt"&gt;--save-dev&lt;/span&gt;

&lt;span class="c"&gt;# Initialize the TypeScript compiler and create the config&lt;/span&gt;
npx tsc &lt;span class="nt"&gt;--init&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This generates a tsconfig.json file. This file is the "brain" of your project. It’s where you tell the compiler exactly how strict you want to be, which version of JavaScript to target, and where to look for your files. &lt;/p&gt;

&lt;h3&gt;
  
  
  1b. Organizing with rootDir and outDir
&lt;/h3&gt;

&lt;p&gt;In a professional workflow, you never want your source code (the stuff you edit) and the distribution code (the stuff that runs) mixed together. It makes version control a nightmare and the project structure confusing. &lt;/p&gt;

&lt;p&gt;To solve this, we dive into the tsconfig.json and configure two crucial settings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;rootDir:&lt;/strong&gt; This points the compiler to our source folder. Usually, we set this to ./src. This is where all our .ts files live.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;outDir:&lt;/strong&gt; This tells the compiler where to dump the generated JavaScript. We usually use ./dist (distribution) or ./build. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By setting these up, your workflow becomes streamlined: you write code in src, run npx tsc, and TypeScript replicates your entire folder structure inside dist, but converted to JavaScript. This keeps your project clean and ready for deployment. &lt;/p&gt;

&lt;h2&gt;
  
  
  2. Beyond Basics: Interfaces, Enums, and Generics
&lt;/h2&gt;

&lt;h3&gt;
  
  
  A. The Power of Interfaces
&lt;/h3&gt;

&lt;p&gt;Interfaces enforce a "contract." If a blueprint says a house needs four windows, TypeScript won't let you build it with three.&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;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nl"&gt;id&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="nl"&gt;username&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="nl"&gt;email&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="nl"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Using an Enum&lt;/span&gt;
    &lt;span class="nl"&gt;tags&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="c1"&gt;// Optional property&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  B. Enums: Eliminating "Magic Strings"
&lt;/h3&gt;

&lt;p&gt;Don't use strings like &lt;code&gt;"admin"&lt;/code&gt; or &lt;code&gt;"guest"&lt;/code&gt; throughout your code. Use &lt;strong&gt;Enums&lt;/strong&gt; to create a single source of truth for constant values.&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="kr"&gt;enum&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Admin&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ADMIN&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;Moderator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;MODERATOR&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;USER&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;myUser&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nikhil_Dev&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nikhil@example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UserRole&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Admin&lt;/span&gt; &lt;span class="c1"&gt;// Type-safe and discoverable&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  C. Generics: Writing Reusable Logic
&lt;/h3&gt;

&lt;p&gt;Generics allow you to create components that work over a variety of types rather than a single one. This is crucial for API responses.&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="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&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;status&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="nl"&gt;data&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="nl"&gt;error&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="c1"&gt;// Now we can reuse this for Users, Products, or Orders&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;userResponse&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ApiResponse&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;myUser&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

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

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. End-to-End Type Safety (Frontend + Backend)
&lt;/h2&gt;

&lt;p&gt;The "Holy Grail" of development is sharing types across your stack. By exporting interfaces from a shared folder, your Frontend knows exactly what the Backend is sending.&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared Function Signatures
&lt;/h3&gt;

&lt;p&gt;Imagine a function that updates a user profile. In TypeScript, we can ensure the payload matches the expected structure before the API call is even made.&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;type&lt;/span&gt; &lt;span class="nx"&gt;UpdateUserPayload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;username&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;tags&lt;/span&gt;&lt;span class="dl"&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;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateUser&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="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;UpdateUserPayload&lt;/span&gt;&lt;span class="p"&gt;):&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="k"&gt;void&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;// TypeScript ensures payload only contains username or tags&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;`/api/user/&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="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;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&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;payload&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;h2&gt;
  
  
  New things I learnt this week🔄
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Power of strict: true:&lt;/strong&gt; Turning this on in tsconfig is like playing a game on "Hard Mode." It forces you to handle null and undefined cases explicitly. It’s annoying at first, but it eliminates about 90% of common runtime bugs. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Targeting Environments:&lt;/strong&gt; I learned that I can write modern ES6+ TypeScript but tell the compiler to output older ES5 code if I need to support legacy environments. &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Type Inference:&lt;/strong&gt; I realized I don't have to define everything. If I write let name = "Nikhil", TypeScript is smart enough to know it's a string. You only need to be explicit when things get complex.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;While the topics that I covered this week were small, they are crucial and of immense importance when building production-ready apps. If you have any questions or feedback, make sure to comment and let me know! &lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>typescript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Week 11: Prisma!</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Wed, 17 Dec 2025 04:57:00 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-11-prisma-3lpo</link>
      <guid>https://dev.to/nikhilsharma6/week-11-prisma-3lpo</guid>
      <description>&lt;p&gt;This week I explored the &lt;strong&gt;Prisma ORM&lt;/strong&gt;, which simplifies our SQL journey by a LOT. Let’s get right into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics Covered✅
&lt;/h2&gt;

&lt;p&gt;Last week, I worked with basic schemas and simple database interactions. But once our data starts to grow and multiple entities are involved, raw SQL queries or loosely typed database access quickly become messy and error-prone.&lt;/p&gt;

&lt;p&gt;That’s where &lt;strong&gt;Prisma&lt;/strong&gt; comes in.&lt;/p&gt;

&lt;p&gt;This week revolved around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding what an ORM actually solves&lt;/li&gt;
&lt;li&gt;Defining a database schema using Prisma&lt;/li&gt;
&lt;li&gt;Generating type-safe database clients&lt;/li&gt;
&lt;li&gt;Performing CRUD operations cleanly and safely&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  1. What is Prisma and why do we need it? 🧠
&lt;/h2&gt;

&lt;p&gt;Prisma is an &lt;strong&gt;ORM (Object Relational Mapper)&lt;/strong&gt;. In simple terms, it acts as a bridge between our database and our application code.&lt;/p&gt;

&lt;p&gt;Without Prisma, we might write raw SQL like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'test@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With Prisma, the same thing looks like:&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;user&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;prisma&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="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;test@gmail.com&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why this matters
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;We don’t manually write SQL for every operation&lt;/li&gt;
&lt;li&gt;Queries become &lt;strong&gt;type-safe&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Refactoring database fields doesn’t silently break things&lt;/li&gt;
&lt;li&gt;Autocomplete + compile-time checks save us from runtime bugs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. Prisma Schema — the single source of truth 📄
&lt;/h2&gt;

&lt;p&gt;First we initialise Prisma in our project (for which you can refer to the &lt;a href="https://www.prisma.io/docs" rel="noopener noreferrer"&gt;docs here&lt;/a&gt;).&lt;br&gt;
At the heart of all generated files lies the &lt;code&gt;schema.prisma&lt;/code&gt; file. This file defines:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;our database connection&lt;/li&gt;
&lt;li&gt;our models (tables)&lt;/li&gt;
&lt;li&gt;relationships between models&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A basic example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This schema:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a &lt;code&gt;User&lt;/code&gt; table&lt;/li&gt;
&lt;li&gt;Automatically enforces uniqueness on email&lt;/li&gt;
&lt;li&gt;Generates types that our editor understands&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once this is written, running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma generate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;creates a fully typed Prisma Client for us — which we can just import in our DB setup files and use as simply as this -&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;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PrismaPg&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;@prisma/adapter-pg&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;PrismaClient&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;@/app/generated/prisma/client&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;adapter&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;PrismaPg&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;connectionString&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;DATABASE_URL&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;prisma&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;PrismaClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;adapter&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;
  
  
  3. Migrations — evolving the database safely 🔁
&lt;/h2&gt;

&lt;p&gt;Databases are never static. Fields get added, removed, or changed. Prisma handles this through &lt;strong&gt;migrations&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx prisma migrate dev &lt;span class="nt"&gt;--name&lt;/span&gt; add-user-model
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a migration file&lt;/li&gt;
&lt;li&gt;Applies changes to the database&lt;/li&gt;
&lt;li&gt;Keeps history of schema evolution&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures our local DB, staging DB, and production DB all stay in sync. And the generated migration files are simply the SQL versions of the queries that we can write easily using Prisma.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. CRUD operations with Prisma ✍️
&lt;/h2&gt;

&lt;p&gt;Prisma makes CRUD operations intuitive and readable.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&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="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nikhil@gmail.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nikhil&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Read
&lt;/h3&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;users&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;prisma&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="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Update
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&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="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Updated Name&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Delete
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;prisma&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="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&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;Each of these operations is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Typed&lt;/li&gt;
&lt;li&gt;Validated at compile time&lt;/li&gt;
&lt;li&gt;Predictable in behaviour&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And to see what parameters these functions expect we can just refer to the docs. &lt;/p&gt;

&lt;h2&gt;
  
  
  5. Relations and foreign keys made simple 🔗
&lt;/h2&gt;

&lt;p&gt;Defining relations in Prisma is surprisingly clean.&lt;/p&gt;

&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;model User {
  id    Int    @id @default(autoincrement())
  posts Post[]
}

model Post {
  id     Int  @id @default(autoincrement())
  title  String
  user   User @relation(fields: [userId], references: [id])
  userId Int
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now Prisma understands:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One user → many posts&lt;/li&gt;
&lt;li&gt;How to join data internally&lt;/li&gt;
&lt;li&gt;How to fetch nested data safely&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fetching related 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;user&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;prisma&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="nf"&gt;findUnique&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;where&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;include&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;posts&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  New things I learnt this week 🔄
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Prisma acts as an intermediary between our code and database - increasing our ease while also giving type safety, which is an absolute game changer.&lt;/li&gt;
&lt;li&gt;Schema-first design prevents an entire class of bugs&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;While Prisma might feel like “just another tool”, it fundamentally changes how confidently we interact with our database. Clean schemas and safe migrations make production systems far more reliable. &lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, make sure to comment and let me know! &lt;strong&gt;Also, if you have any project ideas for me, please drop em in the comments!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I’ll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Week 10: Databases - The Real Backbone of Our Apps!</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 08 Dec 2025 18:14:30 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-10-databases-the-real-backbone-of-our-apps-2k45</link>
      <guid>https://dev.to/nikhilsharma6/week-10-databases-the-real-backbone-of-our-apps-2k45</guid>
      <description>&lt;p&gt;This week, I went deeper into something that quietly run the entire show behind our apps - &lt;strong&gt;databases&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Honestly, this was one of those weeks where everything just &lt;em&gt;clicked&lt;/em&gt;. The more I understood, the more things felt structured and “ohhh, so that's how it's done.” Let’s get right into it!&lt;/p&gt;


&lt;h2&gt;
  
  
  🗂️ Types of Databases
&lt;/h2&gt;

&lt;p&gt;At the highest level, we can split databases into two big families:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;strong&gt;1. SQL Databases (Relational)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;These are structured, rigid, strict but all in a good way.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data lives in &lt;strong&gt;tables&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Tables have &lt;strong&gt;columns&lt;/strong&gt; with fixed types
&lt;/li&gt;
&lt;li&gt;There are &lt;strong&gt;relationships&lt;/strong&gt; between tables
&lt;/li&gt;
&lt;li&gt;Everything is based on a schema we define upfront
&lt;/li&gt;
&lt;li&gt;We interact using &lt;strong&gt;SQL (Structured Query Language)&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples: &lt;strong&gt;PostgreSQL, MySQL, MariaDB, SQL Server&lt;/strong&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  &lt;strong&gt;2. NoSQL Databases (Non-Relational)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;These are way more flexible and relaxed with structure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No fixed schema
&lt;/li&gt;
&lt;li&gt;Great for rapidly changing data
&lt;/li&gt;
&lt;li&gt;Designed for quick reads, massive scale
&lt;/li&gt;
&lt;li&gt;Data can be documents, key-value pairs, graphs, columns…
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples: &lt;strong&gt;MongoDB, Redis, Cassandra, DynamoDB&lt;/strong&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Where MongoDB Fits
&lt;/h2&gt;

&lt;p&gt;MongoDB is a &lt;strong&gt;NoSQL Document Database&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Instead of rows and columns, MongoDB stores data as &lt;strong&gt;documents&lt;/strong&gt; that look like JSON.&lt;/p&gt;

&lt;p&gt;A user record might look like this:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Ayu"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"age"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hobbies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"painting"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"reading"&lt;/span&gt;&lt;span class="p"&gt;]&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;This is super flexible! We can add or remove fields anytime and get no schema alerts.&lt;/p&gt;




&lt;h2&gt;
  
  
  MongoDB Advantages
&lt;/h2&gt;

&lt;p&gt;MongoDB does a bunch of things &lt;em&gt;really&lt;/em&gt; well:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Schema flexibility&lt;/strong&gt; - perfect for fast prototyping
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Horizontal scaling&lt;/strong&gt; - adding more servers is easier
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Great for document-shaped data&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Works naturally with JavaScript&lt;/strong&gt; since it uses JSON-like syntax
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;High read performance&lt;/strong&gt; when queries align with document structure
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we want speed and flexibility(say in a hackathon), MongoDB feels amazing.&lt;/p&gt;




&lt;h2&gt;
  
  
  But MongoDB Has Its Downsides Too
&lt;/h2&gt;

&lt;p&gt;As we scale, we start to notice some cracks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Relationships are painful&lt;/strong&gt;
Joining data across collections feels messy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Data integrity isn’t guaranteed by default&lt;/strong&gt;
If we expect strict correctness → things get tricky.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Query patterns can degrade performance&lt;/strong&gt;
Indexing becomes super important and manually tuned.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Harder to enforce structure&lt;/strong&gt;
Which means bugs can slip into the data layer.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MongoDB is perfect until we need the kind of discipline that big systems demand.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Why Most Companies Still Prefer SQL
&lt;/h2&gt;

&lt;p&gt;Across the industry, SQL remains the default, and once we dig into it, the reasons feel obvious.&lt;/p&gt;

&lt;p&gt;SQL databases like &lt;strong&gt;Postgres&lt;/strong&gt; give us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Structure
&lt;/li&gt;
&lt;li&gt;Predictability
&lt;/li&gt;
&lt;li&gt;Reliability
&lt;/li&gt;
&lt;li&gt;Better Relationships
&lt;/li&gt;
&lt;li&gt;ACID guarantees
&lt;/li&gt;
&lt;li&gt;Rich querying capabilities
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When correctness matters, SQL usually wins.&lt;br&gt;&lt;br&gt;
Say in payments, inventory, authentication, banking, analytics, logistics and so many more. Basically anything where one mistake can cause a lot of trouble, SQL wins.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why SQL (especially Postgres) feels better for many use cases:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Every table has a schema → fewer “surprise bugs”
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Strong JOIN support&lt;/strong&gt; → complex relationships are easy
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transactions&lt;/strong&gt; → either everything succeeds or nothing does
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Indices, constraints, triggers&lt;/strong&gt; → very mature tooling
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Postgres-specific power-ups:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;JSON support (best of both worlds)
&lt;/li&gt;
&lt;li&gt;Window functions
&lt;/li&gt;
&lt;li&gt;Full-text search
&lt;/li&gt;
&lt;li&gt;Extensions like &lt;code&gt;pgvector&lt;/code&gt;, &lt;code&gt;PostGIS&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Postgres feels like that reliable friend who just never drops the ball.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚠️ But SQL Has Some Cons Too
&lt;/h2&gt;

&lt;p&gt;Nothing is perfect.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Schema changes can be heavy
&lt;/li&gt;
&lt;li&gt;Horizontal scaling is harder
&lt;/li&gt;
&lt;li&gt;Rigid structure might feel slow during rapid iteration
&lt;/li&gt;
&lt;li&gt;Requires more planning upfront
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Still, for most of the systems we want to build, SQL’s strengths massively outweigh its weaknesses.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐘 Our Choice This Week: &lt;strong&gt;PostgreSQL&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;So this week was all about &lt;strong&gt;Postgres&lt;/strong&gt;, one of the most powerful SQL databases out there.&lt;/p&gt;

&lt;p&gt;We focused on understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How tables are created
&lt;/li&gt;
&lt;li&gt;How constraints keep our data safe
&lt;/li&gt;
&lt;li&gt;How relationships work using foreign keys
&lt;/li&gt;
&lt;li&gt;How SQL queries are structured
&lt;/li&gt;
&lt;li&gt;Why good database design matters
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And since we’re building in the JavaScript ecosystem, we’ll be pairing Postgres with &lt;strong&gt;Prisma&lt;/strong&gt; as our ORM but that’s a whole topic by itself, so that’s coming next week.&lt;/p&gt;

&lt;p&gt;This week is pure SQL.&lt;/p&gt;




&lt;h2&gt;
  
  
  SQL Examples — With Intuition
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ▶ Creating a Table
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="nb"&gt;SERIAL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="nb"&gt;TEXT&lt;/span&gt; &lt;span class="k"&gt;UNIQUE&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What’s happening?&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
We’re designing a structure where:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;id&lt;/code&gt; auto-increments
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;name&lt;/code&gt; must always exist
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;email&lt;/code&gt; must be unique
&lt;/li&gt;
&lt;li&gt;Postgres will now enforce these rules for us
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the kind of discipline that NoSQL doesn’t enforce.&lt;/p&gt;




&lt;h3&gt;
  
  
  ▶ Inserting Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;INSERT&lt;/span&gt; &lt;span class="k"&gt;INTO&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;VALUES&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Ayu'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'ayu@example.com'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This just means:&lt;br&gt;&lt;br&gt;
“Put a new row into the &lt;code&gt;users&lt;/code&gt; table with these values.”&lt;/p&gt;

&lt;p&gt;SQL has a learning curve which could be slow in the beginning but, as is the case with everything, gets easier with practice.&lt;/p&gt;




&lt;h3&gt;
  
  
  ▶ Querying Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'ayu@example.com'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re pulling only the data that matters.&lt;br&gt;&lt;br&gt;
This precision is where SQL shines.&lt;/p&gt;




&lt;h3&gt;
  
  
  ▶ Updating Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;UPDATE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt;
&lt;span class="k"&gt;SET&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Ayu'&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’re telling Postgres:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;“Find the row where &lt;code&gt;id = 1&lt;/code&gt;”&lt;/li&gt;
&lt;li&gt;“Change the name to Ayu”
&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  ▶ Deleting Data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;DELETE&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;id&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Again - clean and readable(because our use-case is simple – SQL queries can get very complex, but an ORM helps simplify it further).&lt;/p&gt;




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

&lt;p&gt;This week gave us a solid foundation in understanding why databases behave the way they do, and why SQL (especially Postgres) is still the king for most real-world applications. MongoDB is incredible for flexibility and fast-moving projects but SQL is unbeatable for consistency and correctness.&lt;/p&gt;

&lt;p&gt;Next week, we’ll take all this knowledge and plug it into &lt;strong&gt;Prisma&lt;/strong&gt;, making database interactions feel a LOT easier.&lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, make sure to comment and let me know!&lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!  &lt;/p&gt;

</description>
      <category>webdev</category>
      <category>postgres</category>
      <category>beginners</category>
      <category>backend</category>
    </item>
    <item>
      <title>Week 9: Using Recoil in React!</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 01 Dec 2025 18:28:41 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-9-using-recoil-in-react-2m0j</link>
      <guid>https://dev.to/nikhilsharma6/week-9-using-recoil-in-react-2m0j</guid>
      <description>&lt;p&gt;Back after 2 weeks of vacation!(it was actually a continuous battle with so many evaluations and exams at college). During this time I've been covering State Management with context API and Recoil! Let's get right into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics Covered✅
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Context API&lt;/li&gt;
&lt;li&gt;Problems with Context API&lt;/li&gt;
&lt;li&gt;Recoil and why it's better&lt;/li&gt;
&lt;li&gt;Atoms &amp;amp; Selectors&lt;/li&gt;
&lt;li&gt;Recoil hooks (&lt;code&gt;useRecoilState&lt;/code&gt;, &lt;code&gt;useRecoilValue&lt;/code&gt;, &lt;code&gt;useSetRecoilState&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;RecoilRoot&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;When to still use &lt;code&gt;useState&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  1. Starting with the Context API 🧩
&lt;/h1&gt;

&lt;p&gt;Last week, we spoke about prop drilling and how passing props through multiple layers can make your code look messy. The &lt;strong&gt;Context API&lt;/strong&gt; is React’s built-in solution to this.&lt;/p&gt;

&lt;p&gt;It lets you create &lt;strong&gt;global-ish&lt;/strong&gt; state without prop drilling.&lt;/p&gt;

&lt;p&gt;Here’s a tiny example:&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="c1"&gt;// UserContext.jsx&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;createContext&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;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createContext&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="c1"&gt;// App.jsx&lt;/span&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;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="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;UserContext&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;./UserContext&lt;/span&gt;&lt;span class="dl"&gt;"&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;App&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;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="s2"&gt;Nikhil&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="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;value&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;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="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;Parent&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;UserContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Provider&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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// Child.jsx&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;useContext&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;UserContext&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;./UserContext&lt;/span&gt;&lt;span class="dl"&gt;"&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;Child&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;user&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;UserContext&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="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&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;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;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="nx"&gt;Child&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This appears to work well. But it does so only for small and simple apps.&lt;/p&gt;

&lt;h1&gt;
  
  
  2. The problem? 😵‍💫
&lt;/h1&gt;

&lt;p&gt;As our app grows, Context API introduces a few issues:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Re-renders
&lt;/h2&gt;

&lt;p&gt;Any value change in the context re-renders every component that consumes it, even if only one component actually needed the update.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Too many contexts
&lt;/h2&gt;

&lt;p&gt;You often end up creating multiple contexts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UserContext&lt;/li&gt;
&lt;li&gt;ThemeContext&lt;/li&gt;
&lt;li&gt;NotificationContext&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and so on.&lt;/p&gt;

&lt;p&gt;This becomes hard to organise and maintain.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Not a full state management solution
&lt;/h2&gt;

&lt;p&gt;Context wasn't designed for big, complex global state. It's more of a “prop drilling escape hatch”.&lt;/p&gt;

&lt;h1&gt;
  
  
  3. Recoil ⚛️ - The solution
&lt;/h1&gt;

&lt;p&gt;Recoil is a super-lightweight state management library made for React. It fixes the problems above without introducing the complexity of Redux.&lt;/p&gt;

&lt;p&gt;Why Recoil feels so good:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It updates only the components that need the state.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;You don’t need multiple providers — everything sits under one RecoilRoot.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It’s extremely intuitive because it feels like working with React’s useState.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Recoil introduces atoms, which are simply pieces of global state.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  4. Getting started with Recoil
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Step 1: Wrap your app in a RecoilRoot
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// index.jsx&lt;/span&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="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ReactDOM&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-dom/client&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="nx"&gt;App&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;./App&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;RecoilRoot&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;recoil&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;ReactDOM&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;render&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;RecoilRoot&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;App&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;RecoilRoot&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;h2&gt;
  
  
  Step 2:Creating an atom
&lt;/h2&gt;

&lt;p&gt;Atoms store global state. We usually create them in a separate folder and export them from there and then we can use them globally.&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="c1"&gt;// atoms/userAtom.jsx&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;atom&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;recoil&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;userAtom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;atom&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;userAtom&lt;/span&gt;&lt;span class="dl"&gt;"&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nikhil&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3:Using the globally declared states in Components
&lt;/h2&gt;

&lt;p&gt;For this we use majorly three functions&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;useRecoilState → like useState but global
&lt;/li&gt;
&lt;/ol&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;useRecoilState&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;recoil&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;userAtom&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;./atoms/userAtom&lt;/span&gt;&lt;span class="dl"&gt;"&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;UserUpdater&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;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;useRecoilState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userAtom&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;onClick&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="o"&gt;=&amp;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="s2"&gt;Ayu&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;
      Change 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;ol&gt;
&lt;li&gt;useRecoilValue → read-only access- so it basically just gives us the variable and not the function to change its value.
&lt;/li&gt;
&lt;/ol&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;useRecoilValue&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;recoil&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;userAtom&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;./atoms/userAtom&lt;/span&gt;&lt;span class="dl"&gt;"&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;UserDisplay&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRecoilValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userAtom&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="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;user&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;h2&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;ol&gt;
&lt;li&gt;useSetRecoilState → write-only access
&lt;/li&gt;
&lt;/ol&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;useSetRecoilState&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;recoil&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;userAtom&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;./atoms/userAtom&lt;/span&gt;&lt;span class="dl"&gt;"&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;LogoutButton&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;setUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSetRecoilState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userAtom&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="nt"&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setUser&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="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Logout&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Selectors -
&lt;/h3&gt;

&lt;p&gt;Selectors let you derive data from atoms, say computed values. This is how we'd create one.&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;selector&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;recoil&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;userAtom&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;./userAtom&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;capitalisedUserSelector&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selector&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;capitalisedUserSelector&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="kd"&gt;get&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userAtom&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;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&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;And to use it we do 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;useRecoilValue&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;recoil&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;capitalisedUserSelector&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;./atoms/selectors&lt;/span&gt;&lt;span class="dl"&gt;"&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;Display&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRecoilValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;capitalisedUserSelector&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="nt"&gt;h3&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;name&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;h3&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;h1&gt;
  
  
  5. Should we ditch useState now?
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;Not at all.&lt;/strong&gt;&lt;br&gt;
If a state variable is only needed by 1–2 components, using Recoil is unnecessary.&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&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;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&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="mi"&gt;0&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;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;count&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&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="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&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="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="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;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;No reason to make count global here. React’s local state is still perfect for component-specific logic.&lt;br&gt;
We use Recoil only when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Many components need the same state&lt;/li&gt;
&lt;li&gt;Passing props becomes painful&lt;/li&gt;
&lt;li&gt;Context starts slowing down your UI
## Things I found interesting this week&lt;/li&gt;
&lt;li&gt;Seeing how Recoil prevents unnecessary re-renders felt magical. The component isolation makes the app feel snappier.&lt;/li&gt;
&lt;li&gt;Atoms being global state and also visually being "global state" made the learning curve super smooth for me.
## Wrapping up🔄
Interesting week.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; While learning Recoil this week, I actually didn’t know that the library had been archived. Since I had already started, I went ahead and completed it anyway — the concepts are super useful to understand. I’ll be moving to Jotai soon since it’s lightweight, actively maintained, and follows a similar mental model to Recoil, so the transition should feel smooth. &lt;/p&gt;

&lt;p&gt;If you have any questions or feedback, make sure to comment and let me know!&lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Vacation week!</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 17 Nov 2025 16:39:25 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/vacation-week-2489</link>
      <guid>https://dev.to/nikhilsharma6/vacation-week-2489</guid>
      <description>&lt;p&gt;This week wasn’t about new concepts or heavy learning.&lt;br&gt;
Exams are around the corner, I’ve been traveling back and forth between home and college, and it was also the birthday of someone very close to me. So life was a little full in the best ways.&lt;/p&gt;

&lt;p&gt;So this became a vacation week. A breather I honestly needed.&lt;/p&gt;

&lt;p&gt;I'll be back with more next week! Till then, stay consistent.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
    <item>
      <title>Week 8: Routing, Lazy Loading and more in React!🎨</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 10 Nov 2025 18:00:04 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-8-routing-lazy-loading-and-more-in-react-466l</link>
      <guid>https://dev.to/nikhilsharma6/week-8-routing-lazy-loading-and-more-in-react-466l</guid>
      <description>&lt;p&gt;This week I delved into an absolute essential for building a web application! Client-side routing and lazy loading. Let's get right into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics Covered✅
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Client-side routing&lt;/li&gt;
&lt;li&gt;Lazy-loading&lt;/li&gt;
&lt;li&gt;Prop-drilling and its solutions&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  1. Routing📎
&lt;/h3&gt;

&lt;p&gt;Routing is one of the first things that I'd do if I was in a hackathon and needed to get a project up and running quickly. &lt;/p&gt;

&lt;p&gt;React enables us to build single-page applications (SPAs), where navigating between pages doesn’t trigger a &lt;strong&gt;full page reload.&lt;/strong&gt; Instead of reloading the entire site and fetching a new HTML file each time, React uses &lt;strong&gt;client-side routing&lt;/strong&gt;. This means the app dynamically updates the content and changes the URL without requesting a new page from the server. &lt;/p&gt;

&lt;p&gt;This approach makes navigation &lt;strong&gt;faster and smoother&lt;/strong&gt;, since the JavaScript bundle is loaded only once, and React handles rendering the appropriate components for each route.&lt;/p&gt;

&lt;p&gt;This is how we'd change the route in a very superficial way&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";

function Home() {
  const goToAbout = () =&amp;gt; {
    // This causes a full page reload instead of client-side routing
    window.location.href = "/about";
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to Home Page&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={goToAbout}&amp;gt;Go to About&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}

export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But you'll notice that here too , the page hard reloads. To avoid this, we use a library that helps in routing — 'react-router-dom'. Here is how we'd use that to do the same routing as above&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { useNavigate } from "react-router-dom";

function Home() {
  const navigate = useNavigate();

  const goToAbout = () =&amp;gt; {
    // This changes route without reloading the page
    navigate("/about");
  };

  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;Welcome to Home Page&amp;lt;/h1&amp;gt;
      &amp;lt;button onClick={goToAbout}&amp;gt;Go to About&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;
  );
}
export default Home;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there's a little caveat that comes with the &lt;strong&gt;useNavigate()&lt;/strong&gt;hook we use here. It can only be used &lt;strong&gt;inside components that are wrapped by a Router&lt;/strong&gt;. This means that for the useNavigate hook to work, the component must be rendered within a Router context provided by react-router-dom.&lt;br&gt;
This is how our &lt;strong&gt;App() function&lt;/strong&gt; should look for the above to work-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";
import Home from "./Home";
import About from "./About";

function App() {
  return (
    //  useNavigate works only inside components wrapped by a Router
    &amp;lt;BrowserRouter&amp;gt;
      &amp;lt;Routes&amp;gt;
        &amp;lt;Route path="/" element={&amp;lt;Home /&amp;gt;} /&amp;gt;
        &amp;lt;Route path="/about" element={&amp;lt;About /&amp;gt;} /&amp;gt;
      &amp;lt;/Routes&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This stops the page from hard reloading and instead does client-side routing! This is crucial for building fast web applications.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Lazy loading 💤
&lt;/h3&gt;

&lt;p&gt;Another thing we can do to optimise the user's experience is to add lazy-loading to our application. But that is truly useful only if our application has grown large enough.&lt;/p&gt;

&lt;p&gt;But below is an example of how to do it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React, { Suspense } from "react";
import { BrowserRouter, Routes, Route } from "react-router-dom";

// Lazy load the About component
const About = React.lazy(() =&amp;gt; import("./About"));
import Home from "./Home";

function App() {
  return (
    &amp;lt;BrowserRouter&amp;gt;
      {/* Suspense shows fallback while About is being loaded */}
      &amp;lt;Suspense fallback={&amp;lt;div&amp;gt;Loading...&amp;lt;/div&amp;gt;}&amp;gt;
        &amp;lt;Routes&amp;gt;
          &amp;lt;Route path="/" element={&amp;lt;Home /&amp;gt;} /&amp;gt;
          &amp;lt;Route path="/about" element={&amp;lt;About /&amp;gt;} /&amp;gt;
        &amp;lt;/Routes&amp;gt;
      &amp;lt;/Suspense&amp;gt;
    &amp;lt;/BrowserRouter&amp;gt;
  );
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice here that we have to use the &lt;strong&gt;Suspense API&lt;/strong&gt; along with lazy loading else React throws us an error. What this API does is that it allows us to add a "fallback" in case the user's network is too slow and the component cannot load in time. &lt;/p&gt;

&lt;p&gt;Another benefit for lazy loading is that it reduces the initial bundle size of our application, leading to faster load times and improved performance, especially for users with slower internet connections.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Prop Drilling
&lt;/h3&gt;

&lt;p&gt;In one of the earlier blog posts, when we read about various  app optimisation techniques and the need to lower our re-renders we studied how we should push down state to the lowest common ancestors of the &lt;strong&gt;nodes&lt;/strong&gt; that need those state variables. &lt;/p&gt;

&lt;p&gt;But this could still lead to scenarios where the state variable is being passed down through multiple components that don't need the variables for themselves but still have to pass it down. This leads to code that can look very unappealing and overtime become difficult to manage. &lt;/p&gt;

&lt;p&gt;This visually and syntactically bad looking problem is what we call &lt;strong&gt;Prop Drilling&lt;/strong&gt;. &lt;em&gt;Note that prop drilling doesn't have much to do with performance issues as much as it is about the visual and structural complexity it causes.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Below is a small example of prop drilling-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from "react";

function App() {
  const user = "Nikhil";
  return &amp;lt;Parent user={user} /&amp;gt;;
}

function Parent({ user }) {
  //Parent doesn't need 'user', but passes it down anyway
  return &amp;lt;Child user={user} /&amp;gt;;
}

function Child({ user }) {
  return &amp;lt;GrandChild user={user} /&amp;gt;;
}

function GrandChild({ user }) {
  return &amp;lt;h2&amp;gt;Hello, {user}!&amp;lt;/h2&amp;gt;;
}

export default App;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observe here how the user prop travels through multiple components (Parent, Child) that don’t actually need it — they just pass it along so GrandChild can use it. &lt;strong&gt;This is prop drilling.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution -
&lt;/h3&gt;

&lt;p&gt;The solution, as we discussed earlier, is to somehow move all of the state logic outside the components, so that they exist globally. That way, any component that needs it can just call it and use it without it being needed to passed down.&lt;/p&gt;

&lt;p&gt;We can do this using two things- &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;The Context API&lt;/strong&gt; which is built into React but has its limitations like-

&lt;ul&gt;
&lt;li&gt;It can lead to unnecessary re-renders if not used carefully.&lt;/li&gt;
&lt;li&gt;It is not a full-fledged state management solution and may not be suitable for very complex state management needs.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;A state management library&lt;/strong&gt; like RTK(redux tool kit), Recoil(now archived) or some lightweight library built on principles of Recoil, like Jotai or Zustand. These libraries provide more robust solutions for managing global state in larger applications.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;We cover both of these topics in the next blog together!&lt;/p&gt;

&lt;h2&gt;
  
  
  Things I found interesting this week
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Lazy loading was such a cool concept! Seeing the components load one-by-one in the networks tab was really interesting.&lt;/li&gt;
&lt;li&gt;Client-side-routing really tickled a corner of my brain that I did not know wanted to be tickled. Taught me how the URL change in the search bar when we click on different links on a site.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up🔄
&lt;/h2&gt;

&lt;p&gt;Another week gone and some more fundamentals mastered. Really interested to do a state-management library next week. If you have any questions or feedback, make sure to comment and let me know!&lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Week 7: React hooks and more!</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 03 Nov 2025 18:25:04 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-7-react-hooks-and-more-36g4</link>
      <guid>https://dev.to/nikhilsharma6/week-7-react-hooks-and-more-36g4</guid>
      <description>&lt;p&gt;This week was very light. I did not cover anything that was too new or too hard because I needed a break and also wanted to stay in touch! So let's get right into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics Covered✅
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;React returns- the need to return just one parent component&lt;/li&gt;
&lt;li&gt;Re-Renders and minimising them&lt;/li&gt;
&lt;li&gt;Keys in React&lt;/li&gt;
&lt;li&gt;Wrapper components and children&lt;/li&gt;
&lt;li&gt;Hooks&lt;/li&gt;
&lt;li&gt;React.memo&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's get into them in detail.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. React Returns
&lt;/h3&gt;

&lt;p&gt;If you notice that when we try to return sibling components out of a React component, React screams a huge &lt;strong&gt;NO&lt;/strong&gt;. This is because React components must return a single root element. Returning multiple sibling elements isn’t allowed because each component needs one clear root in the virtual DOM tree. This structure enables React’s reconciliation process to work efficiently.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Re-Renders and minimising them
&lt;/h3&gt;

&lt;p&gt;A re-render in React happens when a component’s output (its JSX) is recalculated, and React determines whether the DOM needs to be updated or not. Unnecessary or frequent re-renders can impact performance if not managed properly, thus, we need to minimise them.&lt;/p&gt;

&lt;p&gt;If a parent component re-renders then all its child components re-render along with it. One way to optimise re-renders is to push down state into the lowest common ancestor of the nodes(or components) which need the state. We can also use something called React.memo which we will cover later in this blog.&lt;/p&gt;

&lt;p&gt;Realistically, we would do this by pushing all state outside our core logic and &lt;strong&gt;using a state-management tool&lt;/strong&gt; like Recoil(archived), RTK(Redux Toolkit) or something light like Jotai or Zustand.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Keys in React
&lt;/h3&gt;

&lt;p&gt;Whenever we render something in react which is a list of items like we did in our last blog.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function Todos({todos , setTodos}){
    return &amp;lt;div&amp;gt;
        {todos.map((todo)=&amp;gt;{
            return &amp;lt;div key={todo.id}&amp;gt;
               &amp;lt;h1&amp;gt;{todo.title}&amp;lt;/h1&amp;gt;
               &amp;lt;h1&amp;gt;{todo.description}&amp;lt;/h1&amp;gt;
               {todo.completed?&amp;lt;span&amp;gt;Completed&amp;lt;/span&amp;gt;:&amp;lt;button onClick={()=&amp;gt;{
                handleCompleted(todo._id,todos ,setTodos);
               }}&amp;gt;Mark as done&amp;lt;/button&amp;gt;}
                &amp;lt;/div&amp;gt;
        })}
    &amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, React gives a soft warning when in StrictMode which says -&lt;br&gt;
"Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of TodoList. See fb.me/react-warning-keys for more information."&lt;/p&gt;

&lt;p&gt;What this means is that React needs some sort of a key to recognise which item in the list is being manipulated, deleted, moved around or anything of the sorts.&lt;/p&gt;

&lt;p&gt;We can do this by adding a key prop to each todo as follows&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return &amp;lt;div key={todo._id}&amp;gt; // parent div
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Wrapper Components and children
&lt;/h3&gt;

&lt;p&gt;Wrapper components come in handy when we want uniformity across components written by different people working on a project. In such cases, one person can define a &lt;strong&gt;&lt;em&gt;wrapper component&lt;/em&gt;&lt;/strong&gt; that handles common structure, styling, or logic. Other developers can then pass their component content as children to this wrapper.&lt;/p&gt;

&lt;p&gt;An example of this is as follows-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function Card({ children }) {
  return &amp;lt;div className="card"&amp;gt;{children}&amp;lt;/div&amp;gt;;
}

// Usage
&amp;lt;Card&amp;gt;
  &amp;lt;h2&amp;gt;Title&amp;lt;/h2&amp;gt;
  &amp;lt;p&amp;gt;This is inside the card!&amp;lt;/p&amp;gt;
&amp;lt;/Card&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. React.memo
&lt;/h3&gt;

&lt;p&gt;React.memo is a higher-order component that helps optimize performance by preventing unnecessary re-renders of functional components.&lt;/p&gt;

&lt;p&gt;When you wrap a component with React.memo, React will only re-render it if its props change. If the props remain the same between renders, React skips rendering that component and reuses the previous result.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const TodoItem = React.memo(function TodoItem({ title, description }) {
  console.log("Rendered:", title);
  return (
    &amp;lt;div&amp;gt;
      &amp;lt;h1&amp;gt;{title}&amp;lt;/h1&amp;gt;
      &amp;lt;p&amp;gt;{description}&amp;lt;/p&amp;gt;
    &amp;lt;/div&amp;gt;
  );
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the parent component re-renders but the props (title, description) for a particular TodoItem stay the same, that TodoItem won’t re-render and this saves computation time.&lt;/p&gt;

&lt;p&gt;This is especially useful when you have large lists or expensive UI components that don’t need to update unless their data actually changes. But again this will be handled even better when we use a state-management library.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Hooks
&lt;/h3&gt;

&lt;p&gt;While we did use some hooks like useState and useEffect in last week's project, this was more of an official definition. Hooks are functions that allow us to hook into react state and lifecycle features from functional components. And while there are a lot of hooks, only a handful are used in most code bases.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up🔚
&lt;/h2&gt;

&lt;p&gt;While this week was more theoretical and very light, it does set up some paths that will be very interesting in the upcoming weeks. Especially the state-management part is quite interesting. &lt;strong&gt;Some very intriguing stuff coming in the next weeks.&lt;/strong&gt; If you have any questions or feedback, make sure to comment and let me know!&lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>react</category>
      <category>programming</category>
      <category>beginners</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Week 6: Understanding React through a project🎨</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 27 Oct 2025 18:30:34 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-6-understanding-react-through-a-project-2k7a</link>
      <guid>https://dev.to/nikhilsharma6/week-6-understanding-react-through-a-project-2k7a</guid>
      <description>&lt;p&gt;This week I decided to go deeper into React with a small project. The knowledge required to do this was not vast by any means, but it was nice to move away from snippets and theory to do something more practical. While the project was technically full stack, in this post I'll be delving primarily into the frontend. For the backend, you can see the full code on my GitHub &lt;a href="https://github.com/nikshrma/basic-todo-app" rel="noopener noreferrer"&gt;here&lt;/a&gt;. Let's get right into it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Project - a very basic todo application✅
&lt;/h2&gt;

&lt;p&gt;The project was a simple todo application that consisted of both a backend and a frontend.&lt;/p&gt;

&lt;h3&gt;
  
  
  The backend 🌐
&lt;/h3&gt;

&lt;p&gt;The backend had the following endpoints-&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;POST /todos&lt;/strong&gt; - allows the user to add a todo.
The zod schema for this was
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const createTodo = z.object({
  title: z.string(),
  description: z.string()
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;GET /todos&lt;/strong&gt; - allows the user to get all their existing todos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PUT /completed&lt;/strong&gt; - allows the user to update an existing todo and mark it as done. The zod schema for this was -
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const updateTodo = z.object({
  id: z.string(),
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I already said, the backend is quite simple and we've already covered these topics in our previous blogs, but you can get the full code at my &lt;a href="https://github.com/nikshrma/basic-todo-app" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;. Let's get into the frontend now!&lt;/p&gt;

&lt;h3&gt;
  
  
  The frontend 💡
&lt;/h3&gt;

&lt;p&gt;Now this bit is interesting(gotten a little bored with the backend:). I initialised an empty vite project, cleared the boilerplate code and setup the App.jsx to have only a couple of things — &lt;strong&gt;the rest of the stuff would be structured away neatly for modularity and readability.&lt;/strong&gt;&lt;br&gt;
In the App.jsx I declared my todos as a &lt;strong&gt;state&lt;/strong&gt; variable which would be updated everytime the site re-renders(when a new todo is added or an existing todo is marked as done). For the first render, we would use the &lt;strong&gt;useEffect hook&lt;/strong&gt; to update todos.&lt;/p&gt;
&lt;h3&gt;
  
  
  The useEffect hook🪝 -
&lt;/h3&gt;

&lt;p&gt;Let's see the syntax first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  useEffect(() =&amp;gt; {
    fetch("http://localhost:3000/todos")
      .then(async (res) =&amp;gt; {
        const json = await res.json();
        setTodos(json.todos);
      });
  }, []); 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes it so that what's written in the function executes &lt;strong&gt;only when the React app mounts(or on specified conditions — we'll see that soon).&lt;/strong&gt; This gives us great control over how many fetch requests we send out and on which re-renders the request runs. &lt;/p&gt;

&lt;p&gt;This is controlled through the second argument in the useEffect hook which is called the &lt;strong&gt;dependency array&lt;/strong&gt;. This array is where we pass in the &lt;strong&gt;dependencies&lt;/strong&gt; which decide when the function in the first argument runs.&lt;/p&gt;

&lt;p&gt;For eg. say I add a state variable 'a' to this dependency array. Then whenever 'a' updates, the first function runs. If we leave the &lt;strong&gt;dependency array empty&lt;/strong&gt; then it gives the desired result in our case, which is the fetch request going out only on the app mount.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A couple of things to note here🚨-&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can't make the function in the first argument async. This is because useEffect hook expects the first argument to be a function that returns either nothing or a cleanup function. &lt;strong&gt;But an async function always returns a promise.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;We should not put a state variable in the dependency array that is being updated in the function in the first argument as this would trigger an infinite loop.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The next part in the App.jsx was that it would return a div which would have two components as follows -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;return (
&amp;lt;div&amp;gt;
  &amp;lt;CreateTodo setTodos={setTodos} /&amp;gt;
  &amp;lt;Todos todos={todos} setTodos={setTodos} /&amp;gt;
&amp;lt;/div&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Let's delve into the components-
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. CreateTodo
&lt;/h3&gt;

&lt;p&gt;I created the file 'CreateTodo.jsx' in the components folder in the src folder. &lt;br&gt;
This was a relatively simple component which just returned a div with the input fields necessary to add a new todo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from "react";
export function CreateTodo({setTodos}) {
    const [title, setTitle] = useState("");
    const [description, setDescription] = useState("");
    return (&amp;lt;div&amp;gt;
        &amp;lt;input type="text" placeholder="Title" onChange={(e) =&amp;gt; {
            const value = e.target.value;
            setTitle(value);
        }}&amp;gt;&amp;lt;/input&amp;gt;&amp;lt;br /&amp;gt;
        &amp;lt;input type="text" placeholder="Description" onChange={(e) =&amp;gt; {
            const value = e.target.value;
            setDescription(value);
        }}&amp;gt;&amp;lt;/input&amp;gt;&amp;lt;br /&amp;gt;
        &amp;lt;button onClick={() =&amp;gt; {
            fetch("http://localhost:3000/todos", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json"
                },
                body: JSON.stringify({
                    title: title,
                    description: description
                })

            }).then(async (res) =&amp;gt; {
                fetch("http://localhost:3000/todos")
                    .then(async (res) =&amp;gt; {
                        const json = await res.json();
                        setTodos(json.todos);
                    });
            });
        }}&amp;gt;Add a todo&amp;lt;/button&amp;gt;
    &amp;lt;/div&amp;gt;);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this may seem jarring at first, but let's break it down. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We have two state variables for each of the input fields which update whenever the user types in them. These are used to send the backend calls necessary to add a new todo.&lt;/li&gt;
&lt;li&gt;The button which has a pretty big onClick function which does two things. Firstly, it sends the &lt;strong&gt;POST&lt;/strong&gt; request to add a new todo. You can see the syntax above to send the body with the request. After this, it asynchronously sends another request to &lt;strong&gt;GET&lt;/strong&gt; the newly updated todos from the backend and &lt;strong&gt;updates the todos state variable&lt;/strong&gt;. This causes a re-render in the &lt;code&gt;&amp;lt;Todos&amp;gt;&lt;/code&gt; component and updates the displayed todos.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Todos
&lt;/h3&gt;

&lt;p&gt;This is the component-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export function Todos({todos , setTodos}){
    return &amp;lt;div&amp;gt;
        {todos.map((todo)=&amp;gt;{
            return &amp;lt;div&amp;gt;
               &amp;lt;h1&amp;gt;{todo.title}&amp;lt;/h1&amp;gt;
               &amp;lt;h1&amp;gt;{todo.description}&amp;lt;/h1&amp;gt;
               {todo.completed?&amp;lt;span&amp;gt;Completed&amp;lt;/span&amp;gt;:&amp;lt;button onClick={()=&amp;gt;{
                handleCompleted(todo._id,todos ,setTodos);
               }}&amp;gt;Mark as done&amp;lt;/button&amp;gt;}
                &amp;lt;/div&amp;gt;
        })}
    &amp;lt;/div&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is pretty simple and &lt;strong&gt;a very good use-case of the map method&lt;/strong&gt;. It simply maps all the todos in the variable to be displayed individually in divs on the screen.&lt;/p&gt;

&lt;p&gt;The main magic here is in the handleCompleted function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function handleCompleted(id,todos,setTodos){
    fetch("http://localhost:3000/completed",{
        method:"PUT",
        headers:{
            "Content-Type":"application/json"
        },
        body: JSON.stringify({
            id
        })
    })
    .then (async(res)=&amp;gt;{
        const modifiedTodo = await res.json();
        const newTodos = todos.map((t) =&amp;gt;
        t._id === modifiedTodo.updatedTodo._id ? modifiedTodo.updatedTodo : t
      );

      setTodos(newTodos);
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This sends the &lt;strong&gt;PUT&lt;/strong&gt; request to the endpoint to update the todo to mark it as done. Then it updates the todos to include the new updated todo instead of the old one (very good use-case of the ternary operator).&lt;/p&gt;

&lt;h3&gt;
  
  
  Some new things I learned🧨
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;The useEffect hook - nature of its two arguments!&lt;/li&gt;
&lt;li&gt;How these backend calls do not actually hit the backend unless we include "CORS" in the backend which enables the backend to be hit from any URL.&lt;/li&gt;
&lt;li&gt;The syntax of sending these requests can seem a bit verbose and jarring but we simplify it by using the &lt;strong&gt;Axios library&lt;/strong&gt; which we will study soon!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up🔚
&lt;/h2&gt;

&lt;p&gt;The practicality of this week's assignment kept me hooked. Now that we have some more understanding of React, we dive deeper into React next week. Some more hooks and smaller topics. If you have any questions or feedback, make sure to comment and let me know!&lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Week 5: Dipping into React🎨</title>
      <dc:creator>Nikhil Sharma</dc:creator>
      <pubDate>Mon, 20 Oct 2025 17:06:33 +0000</pubDate>
      <link>https://dev.to/nikhilsharma6/week-5-dipping-into-react-209a</link>
      <guid>https://dev.to/nikhilsharma6/week-5-dipping-into-react-209a</guid>
      <description>&lt;p&gt;This week, I took my first steps towards learning React! For now it was all about learning about state, hooks and most importantly, getting familiar with the syntax. Let's get right into it!&lt;/p&gt;

&lt;h2&gt;
  
  
  Topics Covered✅
&lt;/h2&gt;

&lt;p&gt;The volume of topics I covered this week was modest, and the individual topics were pretty simple once I had dedicated some time to them. Here's a list of the topics I covered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basic File structure in the vite repository&lt;/li&gt;
&lt;li&gt;useState hook&lt;/li&gt;
&lt;li&gt;Components and props&lt;/li&gt;
&lt;li&gt;Hooks vs side-effects&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As usual, these topics were discovered slowly through assignments (and also with some help from the &lt;a href="https://blah.com" rel="noopener noreferrer"&gt;React docs&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating my first React app and learning about useState🚀
&lt;/h2&gt;

&lt;p&gt;I used &lt;strong&gt;Vite&lt;/strong&gt; to create my React app. For that, all I had to do was run&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm create vite@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;in the terminal and then follow the steps on screen.&lt;/p&gt;

&lt;p&gt;Everything I have to deal with for now is in the &lt;strong&gt;src&lt;/strong&gt; folder.&lt;br&gt;
I emptied out the two default css files and went straight to mess with the App.jsx file.&lt;/p&gt;

&lt;p&gt;I then replaced the boilerplate code there with this-&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react'

function App() {
  const [count,setCount] = useState(0);
  function onClickHandler(){
    // count++; not the right way to set state variables
    setCount(count+1);
  }

  return (
      &amp;lt;div&amp;gt;
        &amp;lt;button onClick={onClickHandler}&amp;gt;Counter {count}&amp;lt;/button&amp;gt;
      &amp;lt;/div&amp;gt;    
  )
}

export default App

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

&lt;/div&gt;



&lt;p&gt;And that, was my first React app.&lt;br&gt;
Now I'm aware that this is as simple as it gets, but we all start somewhere right? This helped me learn about the useState hook.&lt;/p&gt;

&lt;p&gt;This &lt;strong&gt;hook&lt;/strong&gt; returns us a variable which is a &lt;strong&gt;state&lt;/strong&gt; variable and a function that updates the state variable. We can give it a default value by specifying it in the brackets.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Something that was a bit strange to me here was how &lt;strong&gt;the App function returns a div&lt;/strong&gt;.&lt;/em&gt; Initially, I thought I was returning plain HTML here, but it was actually JSX — a JavaScript syntax extension that looks like HTML but lets you embed JS expressions inside curly braces leading to some very interesting use-cases.&lt;/p&gt;
&lt;h2&gt;
  
  
  Components and props💡
&lt;/h2&gt;

&lt;p&gt;Then I learned how it was better to have all the different parts of my React App as separate &lt;strong&gt;components&lt;/strong&gt;. &lt;/p&gt;

&lt;p&gt;A component is basically just a function that you declare with a capital first letter. We can use this name as a tag and pass in whatever parameters the function requires as props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react'

function App() {

  const [count,setCount] = useState(0);
  return (
      &amp;lt;div&amp;gt;
        &amp;lt;CustomButton count={count} setCount={setCount}/&amp;gt;
      &amp;lt;/div&amp;gt;    
  )
}
//component
function CustomButton(props){
  function onClickHandler(){
    props.setCount(props.count+1);
  }
  return &amp;lt;button onClick={onClickHandler}&amp;gt;Counter {props.count}&amp;lt;/button&amp;gt;
}

export default App
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here is the exact same app as before, but this has the button as a separate component in the same file named as CustomButton. We pass down both count and setCount to the component with the shown syntax. We can then access all passed parameters which we get as an object called &lt;em&gt;&lt;strong&gt;props&lt;/strong&gt;&lt;/em&gt;. Thus we change the onClickHandler to use 'props.count' and 'props.setCount()'. &lt;/p&gt;

&lt;p&gt;Structuring our app as a bunch of separate components just helps in code readability and modularity.&lt;/p&gt;

&lt;h2&gt;
  
  
  New things I learnt this week🔄
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Structure of a React app&lt;/li&gt;
&lt;li&gt;Hooks - just inbuilt React functions with special purposes&lt;/li&gt;
&lt;li&gt;Using the useState hook&lt;/li&gt;
&lt;li&gt;Object Destructuring - This is one I found very interesting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When we pass down props to a component, we don't necessarily need to use the 'props.' syntax. Instead, we can &lt;strong&gt;destructure the props object&lt;/strong&gt; to individually use all props. The syntax is as follows -&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  function CustomButton({ count , setCount }){
  function onClickHandler(){
    setCount(count+1);
  }
  return 
  &amp;lt;button onClick={onClickHandler}&amp;gt;Counter {count}&amp;lt;/button&amp;gt;
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This feels a bit cleaner to me. And we can destructure any object – not just the props object.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up🔚
&lt;/h2&gt;

&lt;p&gt;This week felt very fresh. A change of topics can do a lot to re-ignite interest. I'll cover some leftover topics I studied later on. Next week, we dive deeper into React with a project. If you have any questions or feedback, make sure to comment and let me know!&lt;/p&gt;

&lt;p&gt;I'll be back next week with more. Until then, stay consistent!&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
