<?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: Sospeter Mong'are</title>
    <description>The latest articles on DEV Community by Sospeter Mong'are (@msnmongare).</description>
    <link>https://dev.to/msnmongare</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%2F117091%2F89122cee-2645-481e-b979-f96819dc9d1b.jpeg</url>
      <title>DEV Community: Sospeter Mong'are</title>
      <link>https://dev.to/msnmongare</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/msnmongare"/>
    <language>en</language>
    <item>
      <title>Testing M-PESA STK Push Callbacks Locally Without Exposing Your Server</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Wed, 18 Mar 2026 13:02:35 +0000</pubDate>
      <link>https://dev.to/msnmongare/testing-m-pesa-stk-push-callbacks-locally-without-exposing-your-server-pdo</link>
      <guid>https://dev.to/msnmongare/testing-m-pesa-stk-push-callbacks-locally-without-exposing-your-server-pdo</guid>
      <description>&lt;p&gt;If you've ever built an M-PESA STK Push integration, you've probably hit this wall: M-PESA needs a publicly accessible callback URL to send payment confirmations, but your app is running on localhost. How do you test this without deploying every single time?&lt;/p&gt;

&lt;p&gt;In this guide I'll show you a simple approach using webhook.site and a small Node.js poller script that automatically forwards M-PESA callbacks to your local machine.&lt;/p&gt;




&lt;h2&gt;
  
  
  What We're Building
&lt;/h2&gt;

&lt;p&gt;When a user completes an STK Push payment, M-PESA sends a POST request to your callback URL with the payment result. Normally that URL has to be publicly accessible. Since localhost isn't public, we'll use webhook.site as a middleman - it catches the callback from M-PESA, and our poller script picks it up and forwards it to our local app automatically.&lt;/p&gt;

&lt;p&gt;The flow looks like this:&lt;/p&gt;

&lt;p&gt;M-PESA → webhook.site → our poller script → localhost&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Node.js installed on your machine&lt;/li&gt;
&lt;li&gt;Your Laravel app running locally&lt;/li&gt;
&lt;li&gt;An M-PESA Daraja API account (sandbox or production)&lt;/li&gt;
&lt;li&gt;Basic understanding of how STK Push works&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 1 - Get a webhook.site URL
&lt;/h2&gt;

&lt;p&gt;Go to webhook.site and you'll immediately get a unique URL that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://webhook.site/f5d500b7-1196-42ef-8ecd-c906e49f7df36
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The part after the last slash is your token. Copy it - you'll need it shortly. Keep this tab open so you can see incoming requests.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 - Store the Callback URL in Your .env
&lt;/h2&gt;

&lt;p&gt;Instead of hardcoding the webhook.site URL in your code, store it in your .env file so you can swap it out easily without touching any code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="py"&gt;MPESA_CALLBACK_URL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;https://webhook.site/f5d500b7-1196-42ef-8ecd-c906e49f7df36&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On production you simply leave this variable out and it falls back to your real callback URL automatically.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 - Update Your ProcessController
&lt;/h2&gt;

&lt;p&gt;In your M-PESA ProcessController where you build the STK Push request, find the CallBackURL line and update it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="s2"&gt;"CallBackURL"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'MPESA_CALLBACK_URL'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;?:&lt;/span&gt; &lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'ipn.MPesa'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this does is simple. If MPESA_CALLBACK_URL is set in your .env it uses that. If it's not set, it falls back to your real route. This means locally it points to webhook.site, and on production it uses your actual callback route - no code changes needed when you deploy.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 4 - Create the Poller Script
&lt;/h2&gt;

&lt;p&gt;This is the magic piece. Create a file called forwarder.js anywhere on your machine - I put mine in the project root. Paste this in:&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;WEBHOOK_TOKEN&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;f5d500b7-1196-42ef-8ecd-c906e49f7df36&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// your token here&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LOCAL_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;http://localhost:8000/ipn/mpesa&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;POLL_INTERVAL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// check every 5 seconds&lt;/span&gt;

&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;lastSeenId&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;()&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`https://webhook.site/token/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;WEBHOOK_TOKEN&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/requests?sorting=newest&amp;amp;per_page=1`&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;data&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;latest&lt;/span&gt; &lt;span class="o"&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;data&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uuid&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;lastSeenId&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="c1"&gt;// already processed this one&lt;/span&gt;

        &lt;span class="nx"&gt;lastSeenId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;uuid&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;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;latest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New callback received! Forwarding to local app...&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;body&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;forward&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;LOCAL_URL&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;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;Content-Type&lt;/span&gt;&lt;span class="dl"&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;application/json&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;body&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Done. Local app responded with status:&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;forward&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&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="nx"&gt;err&lt;/span&gt;&lt;span class="p"&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="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&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;err&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;poll&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;POLL_INTERVAL&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="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Watching webhook.site for incoming callbacks...&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;Replace the WEBHOOK_TOKEN value with your own token from Step 1. The LOCAL_URL should match whatever route your app uses for the M-PESA IPN.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 5 - Run Everything
&lt;/h2&gt;

&lt;p&gt;You'll need two terminals open.&lt;/p&gt;

&lt;p&gt;Terminal 1 - start your Laravel app:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Terminal 2 - start the poller:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;node forwarder.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see this message in Terminal 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Watching webhook.site for incoming callbacks...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 6 - Trigger a Test Payment
&lt;/h2&gt;

&lt;p&gt;Go through your app's deposit flow and trigger an STK Push. Enter your phone number and hit pay. You'll get the prompt on your phone.&lt;/p&gt;

&lt;p&gt;Once you complete the payment, here's what happens automatically:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;M-PESA sends the callback to webhook.site&lt;/li&gt;
&lt;li&gt;Your poller picks it up within 5 seconds&lt;/li&gt;
&lt;li&gt;It forwards the full payload to your local app&lt;/li&gt;
&lt;li&gt;Your local app processes it and updates the database&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You'll see something like this in Terminal 2:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;New&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;callback&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;received!&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Forwarding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app...&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nl"&gt;"Body"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"stkCallback"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="nl"&gt;"ResultCode"&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="nl"&gt;"CheckoutRequestID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"ws_CO_xxxxx"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}}}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Done.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;responded&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;with&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;status:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And your database gets updated just like it would in production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Not Just Use ngrok?
&lt;/h2&gt;

&lt;p&gt;Ngrok is the most common answer to this problem and it works well. However if you're running a licensed script, adding a new public URL can trigger a second domain detection and invalidate your license. The webhook.site approach avoids this completely since your app never gets a new public URL - only the callback endpoint changes temporarily, and only in your local .env.&lt;/p&gt;




&lt;h2&gt;
  
  
  Cleaning Up After Testing
&lt;/h2&gt;

&lt;p&gt;When you're done testing, remove MPESA_CALLBACK_URL from your .env or comment it out:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight properties"&gt;&lt;code&gt;&lt;span class="c"&gt;# MPESA_CALLBACK_URL=https://webhook.site/f5d500b7-1196-42ef-8ecd-c906e49f7df36
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your app will fall back to the real route automatically. Stop the forwarder.js script and you're done. Nothing was changed in your codebase, nothing gets pushed to production.&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;The whole setup takes about 5 minutes and gives you a proper local testing loop for M-PESA callbacks without ngrok, without deploying, and without touching your production environment. The poller script is lightweight, requires no dependencies beyond Node.js, and you can reuse the same approach for any other payment gateway callback - just change the LOCAL_URL to point to the right IPN route.&lt;/p&gt;

</description>
      <category>beginners</category>
      <category>programming</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Run Multiple PHP Versions on Windows and Switch Easily</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Sun, 15 Mar 2026 12:45:08 +0000</pubDate>
      <link>https://dev.to/msnmongare/how-to-run-multiple-php-versions-on-windows-and-switch-easily-a7k</link>
      <guid>https://dev.to/msnmongare/how-to-run-multiple-php-versions-on-windows-and-switch-easily-a7k</guid>
      <description>&lt;p&gt;When working on modern PHP projects like those built with &lt;strong&gt;Laravel&lt;/strong&gt;, you will eventually run into version conflicts.&lt;/p&gt;

&lt;p&gt;One project may require &lt;strong&gt;PHP 8.3&lt;/strong&gt;, while another older project may still run on &lt;strong&gt;PHP 8.1 or 8.2&lt;/strong&gt;. If your system only has one PHP version installed, you will constantly run into errors like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Composer detected issues in your platform:
Your Composer dependencies require a PHP version "&amp;gt;= 8.3.0".
You are running 8.2.12.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead of reinstalling PHP every time you switch projects, the better solution is to install &lt;strong&gt;multiple PHP versions&lt;/strong&gt; and switch between them instantly.&lt;/p&gt;

&lt;p&gt;One of the easiest ways to achieve this on Windows is by using &lt;strong&gt;Scoop&lt;/strong&gt;, a lightweight package manager designed for developers.&lt;/p&gt;

&lt;p&gt;Below is a simple and clean setup.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Install Scoop
&lt;/h2&gt;

&lt;p&gt;Open &lt;strong&gt;PowerShell&lt;/strong&gt; and run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Set-ExecutionPolicy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;RemoteSigned&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Scope&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;CurrentUser&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;irm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;get.scoop.sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;iex&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Confirm installation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;--version&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scoop installs tools into your user directory and avoids the common permission problems that occur with traditional installers.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Add the Versions Bucket
&lt;/h2&gt;

&lt;p&gt;Scoop organizes packages using "buckets". To install multiple PHP versions, you need the versions bucket.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;bucket&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;versions&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This bucket contains packages like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;php81&lt;/li&gt;
&lt;li&gt;php82&lt;/li&gt;
&lt;li&gt;php83&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  3. Install Multiple PHP Versions
&lt;/h2&gt;

&lt;p&gt;You can now install any PHP version you need.&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 powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;php82&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;php83&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check installed packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point both PHP versions exist on your system, but only one will be active at a time.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Switch Between PHP Versions
&lt;/h2&gt;

&lt;p&gt;To switch to &lt;strong&gt;PHP 8.3&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;php83&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To switch to &lt;strong&gt;PHP 8.2&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;reset&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;php82&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Verify the active version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-v&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instantly updates your terminal environment.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Running Your Laravel Project
&lt;/h2&gt;

&lt;p&gt;Once the correct version is active, you can start your project normally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan serve
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the project requires PHP 8.3, switching to php83 will resolve the platform check error.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Approach Is Powerful
&lt;/h2&gt;

&lt;p&gt;Modern development environments rarely use a single runtime version.&lt;/p&gt;

&lt;p&gt;You may have projects such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Legacy project running PHP 8.1&lt;/li&gt;
&lt;li&gt;Production system using PHP 8.2&lt;/li&gt;
&lt;li&gt;New &lt;strong&gt;Laravel 11&lt;/strong&gt; applications requiring PHP 8.3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using Scoop allows you to move between these environments instantly without reinstalling anything.&lt;/p&gt;




&lt;h2&gt;
  
  
  Bonus: Install Other Developer Tools
&lt;/h2&gt;

&lt;p&gt;Scoop can also install common development tools:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;composer&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;nodejs&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;scoop&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;git&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This creates a clean development environment that is easy to maintain and update.&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Managing multiple PHP versions used to be complicated on Windows. With &lt;strong&gt;Scoop&lt;/strong&gt;, the process becomes simple and developer friendly.&lt;/p&gt;

&lt;p&gt;Instead of fighting your environment, you can focus on building applications and switching versions only when necessary.&lt;/p&gt;

&lt;p&gt;For backend developers working with frameworks like &lt;strong&gt;Laravel&lt;/strong&gt;, this setup saves time and prevents version related errors during development.&lt;/p&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>M-PESA DARAJA API - C2B Integration Guide</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Fri, 13 Mar 2026 09:42:47 +0000</pubDate>
      <link>https://dev.to/msnmongare/m-pesa-daraja-api-c2b-integration-guide-djn</link>
      <guid>https://dev.to/msnmongare/m-pesa-daraja-api-c2b-integration-guide-djn</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;If you are building a web or mobile app that needs to receive payments from M-PESA customers in Kenya, the Safaricom Daraja API is the tool you need. This guide will walk you through everything from scratch  no prior API experience required.&lt;/p&gt;

&lt;p&gt;By the end of this guide, you will understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What the C2B API is and how it works&lt;/li&gt;
&lt;li&gt;How to set up and test it in the sandbox using Postman&lt;/li&gt;
&lt;li&gt;What ValidationURL and ConfirmationURL do&lt;/li&gt;
&lt;li&gt;How to take your integration live&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is C2B?
&lt;/h2&gt;

&lt;p&gt;C2B stands for &lt;strong&gt;Customer to Business&lt;/strong&gt;. It refers to the flow of money from an individual customer to your business. When a customer pays your Paybill or Till number via M-PESA, that is a C2B transaction.&lt;/p&gt;

&lt;p&gt;The C2B API allows your application to receive real-time notifications every time a payment comes in, so you can automate things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Marking an order as paid&lt;/li&gt;
&lt;li&gt;Sending a payment receipt to the customer&lt;/li&gt;
&lt;li&gt;Updating your accounting system automatically&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What is Daraja?
&lt;/h2&gt;

&lt;p&gt;Daraja (which means "bridge" in Swahili) is Safaricom's developer portal that gives you access to the M-PESA API. It provides a &lt;strong&gt;sandbox&lt;/strong&gt; (testing) environment where you can simulate payments without using real money, and a &lt;strong&gt;production&lt;/strong&gt; environment for real transactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Portal URL:&lt;/strong&gt; &lt;a href="https://developer.safaricom.co.ke" rel="noopener noreferrer"&gt;https://developer.safaricom.co.ke&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  PART ONE: SANDBOX TESTING
&lt;/h2&gt;

&lt;p&gt;Before using real money, Daraja gives you a sandbox environment to safely test your integration. This is where you should always start.&lt;/p&gt;




&lt;h2&gt;
  
  
  STEP 1 - Create a Daraja Account &amp;amp; App
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Set up your developer profile&lt;/em&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://developer.safaricom.co.ke" rel="noopener noreferrer"&gt;https://developer.safaricom.co.ke&lt;/a&gt; and click &lt;strong&gt;Sign Up&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Fill in your details and verify your email address&lt;/li&gt;
&lt;li&gt;Once logged in, click &lt;strong&gt;"My Apps"&lt;/strong&gt; in the top navigation menu&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Create Sandbox App"&lt;/strong&gt; - give it any name (e.g. "MyShopC2B")&lt;/li&gt;
&lt;li&gt;Under the products section, check &lt;strong&gt;"M-Pesa Sandbox"&lt;/strong&gt; to enable sandbox APIs&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;"Create App"&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your app will now appear in the "My Apps" section. Click on it and you will see two important values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consumer Key&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Acts like your app's username for the API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Consumer Secret&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Acts like your app's password for the API&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💾 &lt;strong&gt;Save These!&lt;/strong&gt; Copy your Consumer Key and Consumer Secret somewhere safe. You will need them for every API call.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  STEP 2 - Get an Access Token
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Authenticate before making any API call&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Every single API request to Daraja requires an access token. Think of it like a &lt;strong&gt;temporary password&lt;/strong&gt; that proves your identity. It expires after 1 hour and you need to generate a new one.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Postman:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Method:&lt;/strong&gt; &lt;code&gt;GET&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL:&lt;/strong&gt; &lt;code&gt;https://sandbox.safaricom.co.ke/oauth/v1/generate?grant_type=client_credentials&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Go to the &lt;strong&gt;Authorization&lt;/strong&gt; tab in Postman:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Auth Type: &lt;strong&gt;Basic Auth&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Username: paste your &lt;strong&gt;Consumer Key&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Password: paste your &lt;strong&gt;Consumer Secret&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Click &lt;strong&gt;Send&lt;/strong&gt;. You should get a response 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;"access_token"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SGWcJPtNtYNPGm1DqBNqZZZZZZ"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"expires_in"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"3599"&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;blockquote&gt;
&lt;p&gt;📋 &lt;strong&gt;Copy It!&lt;/strong&gt; Copy the &lt;code&gt;access_token&lt;/code&gt; value. You will paste it in the Authorization header of every request below.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  STEP 3 - Understanding Your Callback URLs
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;The heart of how C2B notifications work&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Before registering your URLs, it is important to understand what each one does. When a customer makes a payment, Safaricom contacts your server at two different points in the payment flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;📱 Customer Pays  →  🔍 ValidationURL  →  ✅ ConfirmationURL
  (Sends money)      ("Should I allow    ("Payment done,
                          this?")          record it!")
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  ValidationURL - "Should I allow this payment?"
&lt;/h3&gt;

&lt;p&gt;This is called &lt;strong&gt;before&lt;/strong&gt; the payment is processed. Safaricom sends you the payment details and waits for your response. You can accept or reject the payment based on your own business logic - for example, checking if the account number the customer entered actually exists in your system.&lt;/p&gt;

&lt;p&gt;You respond with one of the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Accept&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;payment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ResultCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ResultDesc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Accepted"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Reject&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;payment&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ResultCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"C2B00012"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"ResultDesc"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Rejected"&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;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Note:&lt;/strong&gt; ValidationURL is &lt;strong&gt;optional&lt;/strong&gt;. If you set &lt;code&gt;ResponseType&lt;/code&gt; to &lt;code&gt;"Completed"&lt;/code&gt; when registering, Safaricom skips validation and auto-accepts all payments. This is recommended for beginners.&lt;br&gt;
Validation URL is the URL that receives the validation request from API upon payment submission. The validation URL is only called if external validation on the registered short code is enabled.&lt;br&gt;
(By default, External Validation is disabled)&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h3&gt;
  
  
  ConfirmationURL - "Payment went through, save the details"
&lt;/h3&gt;

&lt;p&gt;This is called &lt;strong&gt;after&lt;/strong&gt; the payment has been successfully processed. At this point, you &lt;strong&gt;cannot&lt;/strong&gt; reject the payment - it has already gone through. This is where your app should record the transaction, update a database, send a receipt, or trigger any other business logic.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;ValidationURL&lt;/th&gt;
&lt;th&gt;ConfirmationURL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;When called&lt;/td&gt;
&lt;td&gt;BEFORE payment is processed&lt;/td&gt;
&lt;td&gt;AFTER payment is processed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Purpose&lt;/td&gt;
&lt;td&gt;Accept or reject the payment&lt;/td&gt;
&lt;td&gt;Record and act on the payment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Your response matters?&lt;/td&gt;
&lt;td&gt;YES - can block the payment&lt;/td&gt;
&lt;td&gt;NO - informational only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Required?&lt;/td&gt;
&lt;td&gt;Optional&lt;/td&gt;
&lt;td&gt;Yes, always required&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;🏪 &lt;strong&gt;Real-world analogy:&lt;/strong&gt; Think of it like a supermarket checkout. The ValidationURL is the cashier checking if your loyalty card is valid before ringing up. The ConfirmationURL is the receipt printer - it just records that the sale happened.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  STEP 4 - Get a Free Callback URL for Testing
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Use webhook.site to capture callbacks&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your ValidationURL and ConfirmationURL must be &lt;strong&gt;publicly accessible HTTPS endpoints&lt;/strong&gt;. For sandbox testing, you do not need a real server - you can use a free tool called &lt;strong&gt;webhook.site&lt;/strong&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://webhook.site" rel="noopener noreferrer"&gt;https://webhook.site&lt;/a&gt; in your browser&lt;/li&gt;
&lt;li&gt;You will instantly get a unique URL like: &lt;code&gt;https://webhook.site/abc-123-xyz&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Copy that URL - you will use it as both your ValidationURL and ConfirmationURL for testing&lt;/li&gt;
&lt;li&gt;Leave the webhook.site tab open. Callbacks from Safaricom will appear here in real time&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;🚫 &lt;strong&gt;URL Rules:&lt;/strong&gt; Never use words like "MPesa", "M-Pesa", or "Safaricom" in your URLs - the system will block them. Also, localhost URLs will not work. Always use a proper HTTPS URL.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  STEP 5 - Register Your Callback URLs
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Tell Safaricom where to send payment notifications&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now you will call the Register URL API to link your callback URLs to your Paybill shortcode.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Postman:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Method:&lt;/strong&gt; &lt;code&gt;POST&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL:&lt;/strong&gt; &lt;code&gt;https://sandbox.safaricom.co.ke/mpesa/c2b/v1/registerurl&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Headers tab - add these two headers:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Header Key&lt;/th&gt;
&lt;th&gt;Header Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Authorization&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Bearer YOUR_ACCESS_TOKEN&lt;/code&gt; (paste the token from Step 2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Content-Type&lt;/td&gt;
&lt;td&gt;&lt;code&gt;application/json&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Body tab - select "raw" and "JSON", then paste:&lt;/strong&gt;&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;"ShortCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"600584"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ResponseType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Completed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Either&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Cancelled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Completed&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ConfirmationURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://webhook.site/your-unique-url"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ValidationURL"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://webhook.site/your-unique-url"&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ShortCode&lt;/td&gt;
&lt;td&gt;The sandbox test Paybill number (600584 is the default sandbox shortcode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ResponseType&lt;/td&gt;
&lt;td&gt;"Completed" means skip validation and auto-accept all payments&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ConfirmationURL&lt;/td&gt;
&lt;td&gt;Your webhook.site URL - where Safaricom sends payment confirmations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ValidationURL&lt;/td&gt;
&lt;td&gt;Your webhook.site URL - where Safaricom asks for approval (optional here)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A successful response looks like:&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;"OriginatorCoversationID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ResponseCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"ResponseDescription"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"success"&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;h2&gt;
  
  
  STEP 6 - Simulate a C2B Payment
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;Pretend a customer is paying you&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now for the fun part - you will simulate a customer sending money to your Paybill. Safaricom provides a test phone number you can use.&lt;/p&gt;

&lt;h3&gt;
  
  
  In Postman:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Method:&lt;/strong&gt; &lt;code&gt;POST&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;URL:&lt;/strong&gt; &lt;code&gt;https://sandbox.safaricom.co.ke/mpesa/c2b/v1/simulate&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use the same Authorization header as before, then paste this JSON body:&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;"ShortCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"600584"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"CommandID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"CustomerPayBillOnline"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"100"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Msisdn"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"254708374149"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"BillRefNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"INV001"&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;ShortCode&lt;/td&gt;
&lt;td&gt;Your sandbox Paybill number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CommandID&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;"CustomerPayBillOnline"&lt;/code&gt; for Paybill, or &lt;code&gt;"CustomerBuyGoodsOnline"&lt;/code&gt; for Till&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Amount&lt;/td&gt;
&lt;td&gt;The amount the simulated customer is paying (in KES)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Msisdn&lt;/td&gt;
&lt;td&gt;The test customer phone number - always use &lt;code&gt;254708374149&lt;/code&gt; in sandbox&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;BillRefNumber&lt;/td&gt;
&lt;td&gt;The account reference - e.g. an invoice number or order ID&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  STEP 7 - Check Your Callback
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;See what your app would receive&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After sending the simulation request, go to your webhook.site tab. Within a few seconds, you should see a POST request arrive. This is exactly the payload your real server would receive when a customer pays.&lt;/p&gt;

&lt;p&gt;It will look something 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;"TransactionType"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Pay Bill"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"TransID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"UCB030CBG1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"TransTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20260311161727"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"TransAmount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"1.00"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"BusinessShortCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"600991"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"BillRefNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"account001"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"InvoiceNumber"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"OrgAccountBalance"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4635316.60"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"ThirdPartyTransID"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"MSISDN"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bbff37cea44ac0b2d964ee0dfb8d2df8513dc7ba1b36129a929fc3fbd6dd4af4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"FirstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"John"&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;th&gt;Explanation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransactionType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Pay Bill&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The type of transaction. Will be "Pay Bill" for Paybill or "Buy Goods" for Till numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;UCB030CBG1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Unique M-PESA transaction ID. Use this as your reference to avoid processing the same payment twice&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransTime&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;20260311161727&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Timestamp of the transaction in &lt;code&gt;YYYYMMDDHHmmss&lt;/code&gt; format. This one means 11 March 2026 at 16:17:27&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TransAmount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;1.00&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The amount the customer paid in KES&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BusinessShortCode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;600991&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your Paybill or Till number that received the payment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BillRefNumber&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;account001&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The account number the customer entered when paying. Use this to identify which customer or order the payment belongs to&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;InvoiceNumber&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(empty)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Optional invoice number. Usually empty for most C2B transactions&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OrgAccountBalance&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;4635316.60&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your Paybill account balance after this transaction was processed&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ThirdPartyTransID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(empty)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;Used in some integrations for a third-party reference. Usually empty&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;MSISDN&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;bbff37c...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The customer's phone number. In sandbox it is returned as a hashed/masked value for privacy.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;FirstName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;John&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The first name of the customer as registered on M-PESA&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; The three most important fields to save in your database are &lt;code&gt;TransID&lt;/code&gt; (to prevent duplicate processing), &lt;code&gt;BillRefNumber&lt;/code&gt; (to identify the customer/order), and &lt;code&gt;TransAmount&lt;/code&gt; (to confirm the correct amount was paid).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a real application, you would read this JSON payload and use the &lt;code&gt;TransAmount&lt;/code&gt;, &lt;code&gt;BillRefNumber&lt;/code&gt;, and &lt;code&gt;MSISDN&lt;/code&gt; fields to update your database and send a receipt to the customer.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Sandbox Note:&lt;/strong&gt; Sandbox callbacks can sometimes be unreliable. If your webhook.site does not receive anything after 30 seconds, try the simulation again. This is a known sandbox issue.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Full C2B Flow Recap
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Step&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;What Happens&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Get Token&lt;/td&gt;
&lt;td&gt;You authenticate with your Consumer Key &amp;amp; Secret and receive a temporary access token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Register URLs&lt;/td&gt;
&lt;td&gt;You tell Safaricom where to send payment notifications&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Customer Pays&lt;/td&gt;
&lt;td&gt;A real or simulated customer sends money to your Paybill or Till number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Validation&lt;/td&gt;
&lt;td&gt;Safaricom hits your ValidationURL asking "should I accept this?" (optional)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Confirmation&lt;/td&gt;
&lt;td&gt;Safaricom hits your ConfirmationURL with the full payment details&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Your App Acts&lt;/td&gt;
&lt;td&gt;Your server reads the payload and updates the database, sends a receipt, etc.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  PART TWO: GOING LIVE
&lt;/h2&gt;

&lt;p&gt;Once your sandbox integration is working correctly, you are ready to go live and process real M-PESA transactions.&lt;/p&gt;




&lt;h2&gt;
  
  
  Prerequisites Before Going Live
&lt;/h2&gt;

&lt;p&gt;Make sure you have all of the following before applying for live credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A working sandbox integration - all steps above tested and confirmed working&lt;/li&gt;
&lt;li&gt;A registered and verified Paybill or Till Number from Safaricom&lt;/li&gt;
&lt;li&gt;An active Safaricom G2 Business Admin account (used to verify your shortcode)&lt;/li&gt;
&lt;li&gt;A real publicly accessible HTTPS server URL (not localhost, not webhook.site) for your callback URLs&lt;/li&gt;
&lt;li&gt;Company documentation: Certificate of incorporation, KRA PIN, and directors' IDs (for businesses)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;🏢 &lt;strong&gt;Get a Paybill First:&lt;/strong&gt; To get a Paybill number, visit a Safaricom shop with your company registration documents. For a Till number, you can apply via the Safaricom self-onboarding portal. Processing takes 24–72 hours.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 1 - Register on the Safaricom G2 Portal
&lt;/h2&gt;

&lt;p&gt;The G2 portal (&lt;a href="https://org.ke.mpesa.com" rel="noopener noreferrer"&gt;https://org.ke.mpesa.com&lt;/a&gt;) is Safaricom's business management platform. You need an account here so Daraja can verify you own the Paybill or Till number you want to use.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send an email to &lt;strong&gt;&lt;a href="mailto:M-PESABusiness@safaricom.co.ke"&gt;M-PESABusiness@safaricom.co.ke&lt;/a&gt;&lt;/strong&gt; requesting a Business Admin account&lt;/li&gt;
&lt;li&gt;Attach required documents: company registration certificate, KRA PIN, directors' IDs, and a signed board resolution&lt;/li&gt;
&lt;li&gt;Safaricom will create your G2 account and send login credentials&lt;/li&gt;
&lt;li&gt;Log in, change your password, and create an "assistant role" user - these credentials will be used in the next step&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Step 2 - Confirm Your Sandbox Integration is Solid
&lt;/h2&gt;

&lt;p&gt;Before applying to go live, make sure all of the following are working in sandbox:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access token generation is working&lt;/li&gt;
&lt;li&gt;URL registration returns a success response&lt;/li&gt;
&lt;li&gt;Simulated payments are triggering callbacks to your server&lt;/li&gt;
&lt;li&gt;Your server is responding with the correct &lt;code&gt;200 OK&lt;/code&gt; responses&lt;/li&gt;
&lt;li&gt;Your database or backend is correctly parsing and saving the callback payload&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Step 3 - Click "Go Live" on the Daraja Portal
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Log into &lt;a href="https://developer.safaricom.co.ke" rel="noopener noreferrer"&gt;https://developer.safaricom.co.ke&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Go to &lt;strong&gt;"My Apps"&lt;/strong&gt; and open your app&lt;/li&gt;
&lt;li&gt;Click the &lt;strong&gt;"Go Live"&lt;/strong&gt; button&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;"Verification by Shortcode"&lt;/strong&gt; as the method&lt;/li&gt;
&lt;li&gt;Enter your Paybill/Till shortcode and your G2 assistant user credentials&lt;/li&gt;
&lt;li&gt;Select the API products you need (e.g. C2B)&lt;/li&gt;
&lt;li&gt;Upload your &lt;strong&gt;test cases&lt;/strong&gt; - a document showing what you tested and the results&lt;/li&gt;
&lt;li&gt;Submit your request&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;⏱️ &lt;strong&gt;Approval Time:&lt;/strong&gt; Safaricom typically takes 24–72 hours to review and approve your live request. You will receive your production credentials by email once approved.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Step 4 - Replace Sandbox Credentials with Live Ones
&lt;/h2&gt;

&lt;p&gt;Once approved, update your application to use production values:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What to Change&lt;/th&gt;
&lt;th&gt;Sandbox → Production&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;API Base URL&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sandbox.safaricom.co.ke&lt;/code&gt; → &lt;code&gt;api.safaricom.co.ke&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consumer Key&lt;/td&gt;
&lt;td&gt;Sandbox key → New live Consumer Key&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Consumer Secret&lt;/td&gt;
&lt;td&gt;Sandbox secret → New live Consumer Secret&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ShortCode&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;600584&lt;/code&gt; (test) → Your actual Paybill/Till number&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Callback URLs&lt;/td&gt;
&lt;td&gt;webhook.site URLs → Your real HTTPS server URLs&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Step 5 - Test a Small Live Transaction
&lt;/h2&gt;

&lt;p&gt;After switching to production credentials, do a small test with real money (e.g. KES 1) to confirm everything works end to end:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pay your Paybill from a real M-PESA number&lt;/li&gt;
&lt;li&gt;Confirm your ConfirmationURL receives the callback&lt;/li&gt;
&lt;li&gt;Verify your database is updated correctly&lt;/li&gt;
&lt;li&gt;Check that the customer receives the expected response or receipt&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;📝 &lt;strong&gt;Keep Logs:&lt;/strong&gt; Always log every transaction in the early stages of going live. Implement retry logic in case of failed callbacks - Safaricom may occasionally retry if your server is slow to respond.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Common Mistakes to Avoid
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;#&lt;/th&gt;
&lt;th&gt;❌ Do NOT do this&lt;/th&gt;
&lt;th&gt;✅ Do this instead&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Include "MPesa" or "Safaricom" in your callback URLs&lt;/td&gt;
&lt;td&gt;Use neutral words in your URLs e.g. &lt;code&gt;/payment/confirm&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Use localhost or 127.0.0.1 as your callback URL&lt;/td&gt;
&lt;td&gt;Host your app or use a tunneling tool like Ngrok (sandbox only)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Use webhook.site/ngrok URLs in production&lt;/td&gt;
&lt;td&gt;Use a real, stable HTTPS server in production&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Apply for all products without knowing what you need&lt;/td&gt;
&lt;td&gt;Plan ahead - decide which APIs you need before going live&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Forget to renew your access token every hour&lt;/td&gt;
&lt;td&gt;Generate a fresh token on each session or add auto-renewal logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Ignore the callback response format&lt;/td&gt;
&lt;td&gt;Always respond with &lt;code&gt;200 OK&lt;/code&gt; and valid &lt;code&gt;ResultCode&lt;/code&gt;/&lt;code&gt;ResultDesc&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Useful Resources
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Resource&lt;/th&gt;
&lt;th&gt;URL&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Daraja Developer Portal&lt;/td&gt;
&lt;td&gt;&lt;a href="https://developer.safaricom.co.ke" rel="noopener noreferrer"&gt;https://developer.safaricom.co.ke&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Daraja API Documentation&lt;/td&gt;
&lt;td&gt;&lt;a href="https://developer.safaricom.co.ke/APIs" rel="noopener noreferrer"&gt;https://developer.safaricom.co.ke/APIs&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Safaricom G2 Business Portal&lt;/td&gt;
&lt;td&gt;&lt;a href="https://org.ke.mpesa.com" rel="noopener noreferrer"&gt;https://org.ke.mpesa.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Test Callback Tool&lt;/td&gt;
&lt;td&gt;&lt;a href="https://webhook.site" rel="noopener noreferrer"&gt;https://webhook.site&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;M-PESA Business Email&lt;/td&gt;
&lt;td&gt;&lt;a href="mailto:M-PESABusiness@safaricom.co.ke"&gt;M-PESABusiness@safaricom.co.ke&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;If you need payment integrations, You can reach out to me on &lt;a href="mailto:sosmongare@gmail"&gt;email&lt;/a&gt;.&lt;/p&gt;

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

</description>
      <category>mpesa</category>
      <category>api</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Understanding APIs: Core Knowledge Every Developer Should Have</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Mon, 09 Mar 2026 20:10:20 +0000</pubDate>
      <link>https://dev.to/msnmongare/understanding-apis-core-knowledge-every-developer-should-have-3ghn</link>
      <guid>https://dev.to/msnmongare/understanding-apis-core-knowledge-every-developer-should-have-3ghn</guid>
      <description>&lt;p&gt;Application Programming Interfaces (APIs) are the backbone of modern software. They enable different applications and services to communicate with each other, exchange data, and perform actions across systems. Whether you are working in frontend, backend, or product development, understanding how APIs work is essential.&lt;/p&gt;

&lt;p&gt;Below are the key concepts every developer should understand when learning APIs.&lt;/p&gt;

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

&lt;p&gt;Most modern APIs follow the REST (Representational State Transfer) architecture. REST defines how resources are structured and accessed over the web. In a REST API, resources such as users, payments, or products are accessed through endpoints.&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 http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /users
GET /orders/123
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;REST helps maintain consistency and makes APIs easier to understand and use.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. HTTP Methods
&lt;/h3&gt;

&lt;p&gt;HTTP methods define the type of action you want to perform on a resource. The most common methods include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GET - Retrieve data from the server&lt;/li&gt;
&lt;li&gt;POST - Create a new resource&lt;/li&gt;
&lt;li&gt;PUT or PATCH - Update an existing resource&lt;/li&gt;
&lt;li&gt;DELETE - Remove a resource&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding when to use each method is fundamental when building or consuming APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Status Codes
&lt;/h3&gt;

&lt;p&gt;Status codes tell you the outcome of an API request. They help developers quickly determine whether a request succeeded or failed.&lt;/p&gt;

&lt;p&gt;Common examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;200 - Request successful&lt;/li&gt;
&lt;li&gt;201 - Resource created successfully&lt;/li&gt;
&lt;li&gt;400 - Bad request&lt;/li&gt;
&lt;li&gt;401 - Unauthorized&lt;/li&gt;
&lt;li&gt;404 - Resource not found&lt;/li&gt;
&lt;li&gt;500 - Server error&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Learning how to interpret these codes is crucial for debugging integrations.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. JSON
&lt;/h3&gt;

&lt;p&gt;Most APIs use JSON (JavaScript Object Notation) as the format for exchanging data. JSON is lightweight and easy for both humans and machines to read.&lt;/p&gt;

&lt;p&gt;Example response:&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;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;101&lt;/span&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;"John Doe"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"john@example.com"&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;Developers should be comfortable reading, writing, and validating JSON structures.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Authentication and Authorization
&lt;/h3&gt;

&lt;p&gt;APIs must ensure that only authorized users or systems can access them. Authentication verifies identity, while authorization determines what actions are allowed.&lt;/p&gt;

&lt;p&gt;Common methods include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API Keys&lt;/li&gt;
&lt;li&gt;OAuth 2.0&lt;/li&gt;
&lt;li&gt;JWT (JSON Web Tokens)&lt;/li&gt;
&lt;li&gt;Basic Authentication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Many business APIs rely heavily on authentication mechanisms, such as the &lt;strong&gt;Stripe API&lt;/strong&gt;, &lt;strong&gt;Twilio API&lt;/strong&gt;, and &lt;strong&gt;M-Pesa Daraja API&lt;/strong&gt;.&lt;/p&gt;

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

&lt;p&gt;HTTP headers provide additional information about the request or response.&lt;/p&gt;

&lt;p&gt;Common headers include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authorization - used to pass authentication tokens&lt;/li&gt;
&lt;li&gt;Content-Type - defines the format of the request body&lt;/li&gt;
&lt;li&gt;Accept - indicates the expected response format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding headers helps you control how APIs process requests.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Request and Response Structure
&lt;/h3&gt;

&lt;p&gt;An API request can contain several components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Path parameters&lt;/li&gt;
&lt;li&gt;Query parameters&lt;/li&gt;
&lt;li&gt;Request body&lt;/li&gt;
&lt;li&gt;Headers&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /transactions?limit=10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The response typically returns structured data along with a status code.&lt;/p&gt;

&lt;h3&gt;
  
  
  8. Error Handling
&lt;/h3&gt;

&lt;p&gt;Well-designed APIs return clear error messages when something goes wrong.&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 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;"error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invalid_request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Missing required field"&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;Understanding error responses helps developers quickly diagnose and fix issues during integration.&lt;/p&gt;

&lt;h3&gt;
  
  
  9. Pagination
&lt;/h3&gt;

&lt;p&gt;When APIs return large datasets, they often split results into smaller pages.&lt;/p&gt;

&lt;p&gt;Common parameters include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;limit&lt;/li&gt;
&lt;li&gt;offset&lt;/li&gt;
&lt;li&gt;cursor&lt;/li&gt;
&lt;/ul&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET /transactions?limit=20&amp;amp;offset=40
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pagination ensures efficient data retrieval without overloading the system.&lt;/p&gt;

&lt;h3&gt;
  
  
  10. Rate Limiting
&lt;/h3&gt;

&lt;p&gt;To protect infrastructure, many APIs limit how many requests a client can make within a given time period.&lt;/p&gt;

&lt;p&gt;If the limit is exceeded, the server may return:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;429 Too Many Requests
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Developers must design their systems to handle rate limits gracefully.&lt;/p&gt;

&lt;h3&gt;
  
  
  11. Webhooks
&lt;/h3&gt;

&lt;p&gt;Webhooks allow systems to receive real-time notifications when an event occurs, instead of constantly polling an API.&lt;/p&gt;

&lt;p&gt;For example, a payment service may send a webhook when a payment is completed. This pattern is widely used in platforms like the &lt;strong&gt;Stripe API&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  12. API Documentation
&lt;/h3&gt;

&lt;p&gt;Good documentation is essential when working with APIs. Many APIs use tools like &lt;strong&gt;Swagger&lt;/strong&gt;, &lt;strong&gt;Postman&lt;/strong&gt;, or the &lt;strong&gt;OpenAPI Specification&lt;/strong&gt; to clearly describe endpoints, parameters, and responses.&lt;/p&gt;

&lt;p&gt;Being able to read and interpret API documentation is a critical developer skill.&lt;/p&gt;

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

&lt;p&gt;APIs power the digital world. From payment processing to messaging services and cloud platforms, they enable systems to interact seamlessly.&lt;/p&gt;

&lt;p&gt;For anyone building modern applications, understanding REST, HTTP methods, status codes, JSON, authentication, headers, pagination, rate limits, and webhooks is not optional. It is foundational knowledge that every developer should master. &lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>beginners</category>
      <category>api</category>
    </item>
    <item>
      <title>What is Vite</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Wed, 18 Feb 2026 09:47:07 +0000</pubDate>
      <link>https://dev.to/msnmongare/what-is-vite-181o</link>
      <guid>https://dev.to/msnmongare/what-is-vite-181o</guid>
      <description>&lt;p&gt;If you just downloaded a React project and saw something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then an error mentioning &lt;strong&gt;vite&lt;/strong&gt;, you might be wondering:&lt;/p&gt;

&lt;p&gt;What exactly is Vite?&lt;/p&gt;

&lt;p&gt;Let us break it down in simple terms.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Is Vite?
&lt;/h2&gt;

&lt;p&gt;Vite is a tool that helps you &lt;strong&gt;run and build modern frontend applications&lt;/strong&gt; like React, Vue, or plain JavaScript apps.&lt;/p&gt;

&lt;p&gt;You can think of it as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A development server&lt;/li&gt;
&lt;li&gt;A build tool&lt;/li&gt;
&lt;li&gt;A translator for modern JavaScript&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All combined into one.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Do We Need Vite?
&lt;/h2&gt;

&lt;p&gt;Modern frontend code includes things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSX (used in React)&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;ES Modules&lt;/li&gt;
&lt;li&gt;CSS imports inside JavaScript&lt;/li&gt;
&lt;li&gt;Modern JavaScript features&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Browsers do not fully understand all of this directly.&lt;/p&gt;

&lt;p&gt;Vite takes your modern code and converts it into something the browser can understand.&lt;/p&gt;

&lt;p&gt;Without a tool like Vite, your React app would not run properly in the browser.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Does Vite Actually Do?
&lt;/h2&gt;

&lt;p&gt;When you 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 run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vite:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Starts a local development server&lt;br&gt;
Usually something like:&lt;br&gt;
&lt;a href="http://localhost:5173" rel="noopener noreferrer"&gt;http://localhost:5173&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Loads your app into the browser&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Watches your files for changes&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Automatically refreshes the browser when you save changes&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This makes development fast and smooth.&lt;/p&gt;




&lt;h2&gt;
  
  
  Simple Analogy
&lt;/h2&gt;

&lt;p&gt;Imagine building a car:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React is the engine components&lt;/li&gt;
&lt;li&gt;Your code is the raw material&lt;/li&gt;
&lt;li&gt;The browser is the driver&lt;/li&gt;
&lt;li&gt;Vite is the factory that assembles everything so the car can run&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without the factory, the parts do not become a working car.&lt;/p&gt;




&lt;h2&gt;
  
  
  Is Vite Part of React?
&lt;/h2&gt;

&lt;p&gt;No.&lt;/p&gt;

&lt;p&gt;React is just a JavaScript library for building user interfaces.&lt;/p&gt;

&lt;p&gt;It does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start a server&lt;/li&gt;
&lt;li&gt;Compile files&lt;/li&gt;
&lt;li&gt;Bundle your code&lt;/li&gt;
&lt;li&gt;Optimize your app for production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vite is what makes your React project actually run during development and prepares it for deployment.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Is Vite Popular?
&lt;/h2&gt;

&lt;p&gt;Vite is popular because it is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Very fast&lt;/li&gt;
&lt;li&gt;Simple to configure&lt;/li&gt;
&lt;li&gt;Lightweight&lt;/li&gt;
&lt;li&gt;Easy to set up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Compared to older tools like Webpack, Vite starts almost instantly and reloads changes much faster.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happens If Vite Is Missing?
&lt;/h2&gt;

&lt;p&gt;If you see an error like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'vite' is not recognized as an internal or external command
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It usually means:&lt;/p&gt;

&lt;p&gt;You have not installed project dependencies yet.&lt;/p&gt;

&lt;p&gt;The fix is usually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;If you are building modern frontend apps, Vite is the tool that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Runs your app locally&lt;/li&gt;
&lt;li&gt;Converts modern code to browser ready code&lt;/li&gt;
&lt;li&gt;Makes development faster&lt;/li&gt;
&lt;li&gt;Prepares your app for production&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In short:&lt;/p&gt;

&lt;p&gt;Vite is the engine that makes your frontend project come alive.&lt;/p&gt;

</description>
      <category>react</category>
      <category>vite</category>
      <category>webdev</category>
      <category>beginners</category>
    </item>
    <item>
      <title>The Engineer as a Decision Maker, Not a Developer</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Wed, 11 Feb 2026 08:43:49 +0000</pubDate>
      <link>https://dev.to/msnmongare/the-engineer-as-a-decision-maker-not-a-developer-lid</link>
      <guid>https://dev.to/msnmongare/the-engineer-as-a-decision-maker-not-a-developer-lid</guid>
      <description>&lt;p&gt;For years, the software industry has romanticized the image of the engineer as someone who writes elegant code, masters frameworks, and ships features at lightning speed. But the most valuable engineers today are not defined by how fast they type or how many languages they know.&lt;/p&gt;

&lt;p&gt;They are defined by the quality of their decisions.&lt;/p&gt;

&lt;p&gt;The shift from developer to decision maker is what separates average engineers from high impact engineers. And in a world where AI can generate code in seconds, this shift is no longer optional. It is essential.&lt;/p&gt;

&lt;h2&gt;
  
  
  Code Is a Tool. Decisions Create Value.
&lt;/h2&gt;

&lt;p&gt;A junior developer focuses on implementation:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I build this?&lt;/li&gt;
&lt;li&gt;Which syntax should I use?&lt;/li&gt;
&lt;li&gt;How do I fix this error?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A decision making engineer asks different questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Should we build this at all?&lt;/li&gt;
&lt;li&gt;What problem are we actually solving?&lt;/li&gt;
&lt;li&gt;Is this the simplest solution?&lt;/li&gt;
&lt;li&gt;What are the long term consequences?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The difference is subtle but powerful.&lt;/p&gt;

&lt;p&gt;Code is the output. Decisions determine whether that output is useful, scalable, secure, and aligned with business goals.&lt;/p&gt;

&lt;p&gt;An engineer who understands tradeoffs between performance and cost, speed and maintainability, abstraction and simplicity becomes far more valuable than someone who only knows how to implement tickets.&lt;/p&gt;

&lt;h2&gt;
  
  
  Every Line of Code Is a Liability
&lt;/h2&gt;

&lt;p&gt;Writing code feels productive. But every line added is something that must be maintained, tested, debugged, documented, and eventually refactored.&lt;/p&gt;

&lt;p&gt;A decision driven engineer understands that sometimes the best decision is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reuse instead of rebuild.&lt;/li&gt;
&lt;li&gt;Integrate instead of invent.&lt;/li&gt;
&lt;li&gt;Simplify instead of scale prematurely.&lt;/li&gt;
&lt;li&gt;Delete instead of add.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Strong engineers reduce complexity. They do not increase it just to prove skill.&lt;/p&gt;

&lt;p&gt;They think in systems, not just scripts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Choices Are Business Decisions
&lt;/h2&gt;

&lt;p&gt;Choosing a database is not just a technical act. It affects:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hosting costs&lt;/li&gt;
&lt;li&gt;Scaling strategy&lt;/li&gt;
&lt;li&gt;Hiring requirements&lt;/li&gt;
&lt;li&gt;Vendor lock in&lt;/li&gt;
&lt;li&gt;Performance under growth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Choosing to microservice too early can slow a startup. Choosing to ignore observability can cost days in downtime. Choosing the wrong payment flow can affect revenue.&lt;/p&gt;

&lt;p&gt;Engineers who understand that architecture impacts money, users, and growth move from being implementers to strategic contributors.&lt;/p&gt;

&lt;p&gt;They stop waiting for instructions. They start shaping direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Decision Making Requires Context
&lt;/h2&gt;

&lt;p&gt;You cannot make strong engineering decisions without understanding:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The product vision&lt;/li&gt;
&lt;li&gt;The customer pain points&lt;/li&gt;
&lt;li&gt;The revenue model&lt;/li&gt;
&lt;li&gt;The team capacity&lt;/li&gt;
&lt;li&gt;The timeline constraints&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why the best engineers attend product meetings, ask business questions, and care about metrics.&lt;/p&gt;

&lt;p&gt;They do not hide behind code.&lt;/p&gt;

&lt;p&gt;They know that a technically perfect solution that misses market timing is a failure.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Is Raising the Bar
&lt;/h2&gt;

&lt;p&gt;With AI tools generating boilerplate, scaffolding APIs, and even debugging, the value of raw coding skill is decreasing.&lt;/p&gt;

&lt;p&gt;The competitive advantage is now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Problem framing&lt;/li&gt;
&lt;li&gt;Tradeoff analysis&lt;/li&gt;
&lt;li&gt;Risk evaluation&lt;/li&gt;
&lt;li&gt;Architectural thinking&lt;/li&gt;
&lt;li&gt;Clear communication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anyone can generate code.&lt;/p&gt;

&lt;p&gt;Not everyone can decide what should be generated.&lt;/p&gt;

&lt;h2&gt;
  
  
  From Task Taker to Owner
&lt;/h2&gt;

&lt;p&gt;A developer waits for a ticket.&lt;/p&gt;

&lt;p&gt;A decision making engineer asks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What outcome are we targeting?&lt;/li&gt;
&lt;li&gt;Is this the highest priority problem?&lt;/li&gt;
&lt;li&gt;Is there a faster way to deliver impact?&lt;/li&gt;
&lt;li&gt;What will break in six months if we do this?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ownership changes everything.&lt;/p&gt;

&lt;p&gt;Instead of “I implemented what I was told,” the mindset becomes, “I am responsible for the result.”&lt;/p&gt;

&lt;p&gt;That shift transforms careers.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Become a Decision Driven Engineer
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Study tradeoffs, not just syntax.&lt;br&gt;
Learn why systems fail. Learn scaling patterns. Learn architectural mistakes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Understand the business model.&lt;br&gt;
If the product makes money from transactions, uptime and performance matter differently than if it makes money from subscriptions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simplify aggressively.&lt;br&gt;
Complexity compounds. Simplicity scales.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Communicate clearly.&lt;br&gt;
The best decisions are useless if you cannot explain them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Think long term.&lt;br&gt;
Ask what this decision looks like at 10x growth.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Future Engineer
&lt;/h2&gt;

&lt;p&gt;The future engineer is not the person who knows the most frameworks.&lt;/p&gt;

&lt;p&gt;It is the person who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Knows when not to use one.&lt;/li&gt;
&lt;li&gt;Understands impact beyond code.&lt;/li&gt;
&lt;li&gt;Aligns technology with strategy.&lt;/li&gt;
&lt;li&gt;Chooses clarity over cleverness.&lt;/li&gt;
&lt;li&gt;Optimizes for outcomes, not ego.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code is still important. But code is no longer the differentiator.&lt;/p&gt;

&lt;p&gt;Judgment is.&lt;/p&gt;

&lt;p&gt;And the engineers who master decision making will shape products, teams, and industries long after the syntax they once memorized becomes obsolete.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>software</category>
      <category>productivity</category>
    </item>
    <item>
      <title>React Hooks Explained (Beginner-Friendly)</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Mon, 09 Feb 2026 05:08:00 +0000</pubDate>
      <link>https://dev.to/msnmongare/react-hooks-explained-beginner-friendly-3ggn</link>
      <guid>https://dev.to/msnmongare/react-hooks-explained-beginner-friendly-3ggn</guid>
      <description>&lt;h2&gt;
  
  
  First: What is a Hook?
&lt;/h2&gt;

&lt;p&gt;A &lt;strong&gt;Hook&lt;/strong&gt; is just a &lt;strong&gt;special function React gives you&lt;/strong&gt; to “plug into” React features like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;Lifecycle&lt;/li&gt;
&lt;li&gt;Context&lt;/li&gt;
&lt;li&gt;Performance optimization&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hooks always:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Start with &lt;code&gt;use&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Are called &lt;strong&gt;inside components only&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Follow predictable rules&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Core Hooks (You should learn these)
&lt;/h2&gt;

&lt;p&gt;These are the hooks you’ll use in &lt;strong&gt;almost every React app&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1️⃣ &lt;code&gt;useState&lt;/code&gt; — Store changing data
&lt;/h2&gt;

&lt;p&gt;You already know this 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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form inputs&lt;/li&gt;
&lt;li&gt;Toggles&lt;/li&gt;
&lt;li&gt;Counters&lt;/li&gt;
&lt;li&gt;Loading states&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Component-level variables that cause re-render when changed.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2️⃣ &lt;code&gt;useEffect&lt;/code&gt; — Run side effects
&lt;/h2&gt;

&lt;p&gt;Also familiar now.&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;fetchData&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;Use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;API calls&lt;/li&gt;
&lt;li&gt;Subscriptions&lt;/li&gt;
&lt;li&gt;Timers&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Run this after rendering or when something changes.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3️⃣ &lt;code&gt;useContext&lt;/code&gt; — Read global data
&lt;/h2&gt;

&lt;p&gt;Used with React Context.&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;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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logged-in user&lt;/li&gt;
&lt;li&gt;Theme&lt;/li&gt;
&lt;li&gt;Language&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Read shared data without passing props.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Secondary Hooks (Learn after basics)
&lt;/h2&gt;

&lt;p&gt;These make apps cleaner and faster.&lt;/p&gt;




&lt;h2&gt;
  
  
  4️⃣ &lt;code&gt;useRef&lt;/code&gt; — Store values without re-rendering
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;inputRef&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useRef&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accessing DOM elements&lt;/li&gt;
&lt;li&gt;Storing values that shouldn’t trigger UI updates&lt;/li&gt;
&lt;li&gt;Timers, counters, previous values&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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="nx"&gt;inputRef&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;focus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“A box that holds data across renders without re-rendering.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  5️⃣ &lt;code&gt;useReducer&lt;/code&gt; — Advanced state logic
&lt;/h2&gt;

&lt;p&gt;Alternative to &lt;code&gt;useState&lt;/code&gt;.&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;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useReducer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;State logic is complex&lt;/li&gt;
&lt;li&gt;Many related state updates exist&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Backend analogy:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Reducer = controller logic&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6️⃣ &lt;code&gt;useMemo&lt;/code&gt; — Cache expensive calculations
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&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;heavyCalculation&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use it to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Prevent unnecessary recalculations&lt;/li&gt;
&lt;li&gt;Improve performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Only recalculate if inputs change.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  7️⃣ &lt;code&gt;useCallback&lt;/code&gt; — Cache functions
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;doSomething&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;Use it when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passing functions to child components&lt;/li&gt;
&lt;li&gt;Preventing unnecessary re-renders&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Same function instance unless dependencies change.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Advanced / Rare Hooks (Know they exist)
&lt;/h2&gt;

&lt;p&gt;You don’t need these early on, but it’s good to know them.&lt;/p&gt;




&lt;h2&gt;
  
  
  8️⃣ &lt;code&gt;useLayoutEffect&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Like &lt;code&gt;useEffect&lt;/code&gt;, but runs &lt;strong&gt;before browser paint&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Use only when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You need to measure layout sizes&lt;/li&gt;
&lt;li&gt;You see flickering UI issues&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Rarely needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  9️⃣ &lt;code&gt;useImperativeHandle&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Controls what a parent can access from a child component.&lt;/p&gt;

&lt;p&gt;Used with &lt;code&gt;forwardRef&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Advanced use cases only.&lt;/p&gt;




&lt;h2&gt;
  
  
  10️⃣ &lt;code&gt;useId&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Generates unique IDs.&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;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;useId&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Form inputs&lt;/li&gt;
&lt;li&gt;Accessibility (labels)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Custom Hooks (VERY IMPORTANT)
&lt;/h2&gt;

&lt;p&gt;You can create your &lt;strong&gt;own hooks&lt;/strong&gt;.&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;useGroups&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;groups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setGroups&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;fetchGroups&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;setGroups&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;groups&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;Use them to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reuse logic&lt;/li&gt;
&lt;li&gt;Keep components clean&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mental model:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Extract reusable logic into a function.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Beginner Learning Order (Recommended)
&lt;/h2&gt;

&lt;p&gt;Here’s the &lt;strong&gt;safe learning path&lt;/strong&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useRef&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useMemo&lt;/code&gt; &amp;amp; &lt;code&gt;useCallback&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Custom Hooks&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  What You Should NOT Do as a Beginner 🚫
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Don’t memorize all hooks&lt;/li&gt;
&lt;li&gt;Don’t use &lt;code&gt;useMemo&lt;/code&gt; everywhere&lt;/li&gt;
&lt;li&gt;Don’t optimize too early&lt;/li&gt;
&lt;li&gt;Don’t jump to advanced hooks before basics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Quick Summary Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Hook&lt;/th&gt;
&lt;th&gt;Purpose&lt;/th&gt;
&lt;th&gt;Learn When&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;useState&lt;/td&gt;
&lt;td&gt;Local state&lt;/td&gt;
&lt;td&gt;Day 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useEffect&lt;/td&gt;
&lt;td&gt;Side effects&lt;/td&gt;
&lt;td&gt;Day 1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useContext&lt;/td&gt;
&lt;td&gt;Global state&lt;/td&gt;
&lt;td&gt;Early&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useRef&lt;/td&gt;
&lt;td&gt;DOM &amp;amp; mutable values&lt;/td&gt;
&lt;td&gt;Early&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useReducer&lt;/td&gt;
&lt;td&gt;Complex logic&lt;/td&gt;
&lt;td&gt;Intermediate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useMemo&lt;/td&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;Later&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;useCallback&lt;/td&gt;
&lt;td&gt;Stable functions&lt;/td&gt;
&lt;td&gt;Later&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Final Takeaway
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;You don’t need all hooks to build real apps.&lt;br&gt;
You need to &lt;strong&gt;understand a few deeply&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you master:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useContext&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can build &lt;strong&gt;most production apps&lt;/strong&gt; comfortably.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>The First Big Mistake: Thinking Software Engineering Is Just Coding</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Wed, 04 Feb 2026 10:42:02 +0000</pubDate>
      <link>https://dev.to/msnmongare/the-first-big-mistake-thinking-software-engineering-is-just-coding-490d</link>
      <guid>https://dev.to/msnmongare/the-first-big-mistake-thinking-software-engineering-is-just-coding-490d</guid>
      <description>&lt;p&gt;One of the biggest misconceptions shaping today’s AI panic is the belief that &lt;strong&gt;software engineering equals writing code&lt;/strong&gt;. From that flawed assumption comes an even bigger conclusion: &lt;em&gt;“If AI can write code, then AI will replace software engineers.”&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This logic sounds convincing-until you understand what software engineering actually is.&lt;/p&gt;

&lt;h3&gt;
  
  
  Coding Is the Output, Not the Job
&lt;/h3&gt;

&lt;p&gt;Writing code is only the &lt;strong&gt;visible output&lt;/strong&gt; of software engineering, not the work itself.&lt;/p&gt;

&lt;p&gt;Software engineering is about:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understanding ambiguous problems&lt;/li&gt;
&lt;li&gt;Translating human needs into technical systems&lt;/li&gt;
&lt;li&gt;Designing architectures that scale&lt;/li&gt;
&lt;li&gt;Making trade-offs between performance, cost, security, and time&lt;/li&gt;
&lt;li&gt;Anticipating failure, misuse, and edge cases&lt;/li&gt;
&lt;li&gt;Maintaining systems long after they are written&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code is simply the medium through which these decisions are expressed.&lt;/p&gt;

&lt;p&gt;If you remove the thinking, the code becomes meaningless.&lt;/p&gt;

&lt;h3&gt;
  
  
  Software Engineering Is Decision-Making Under Constraints
&lt;/h3&gt;

&lt;p&gt;Real-world systems don’t fail because someone didn’t know syntax.&lt;br&gt;
They fail because:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requirements were misunderstood&lt;/li&gt;
&lt;li&gt;Assumptions were wrong&lt;/li&gt;
&lt;li&gt;Systems didn’t scale as expected&lt;/li&gt;
&lt;li&gt;Trade-offs weren’t thought through&lt;/li&gt;
&lt;li&gt;Human behavior wasn’t considered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are &lt;strong&gt;engineering problems&lt;/strong&gt;, not typing problems.&lt;/p&gt;

&lt;p&gt;AI can generate code, but it does not &lt;em&gt;own responsibility&lt;/em&gt;. It doesn’t sit in meetings to clarify vague requirements. It doesn’t get paged at 2 a.m. when production is down. It doesn’t weigh business risk against technical purity.&lt;/p&gt;

&lt;p&gt;Engineers do.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI Is Powerful at Code - Weak at Context
&lt;/h3&gt;

&lt;p&gt;AI excels at:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pattern matching&lt;/li&gt;
&lt;li&gt;Rewriting existing logic&lt;/li&gt;
&lt;li&gt;Generating boilerplate&lt;/li&gt;
&lt;li&gt;Speeding up repetitive tasks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But software lives in &lt;strong&gt;context&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Business goals change&lt;/li&gt;
&lt;li&gt;Users behave unpredictably&lt;/li&gt;
&lt;li&gt;Legal and compliance rules evolve&lt;/li&gt;
&lt;li&gt;Systems interact with messy, legacy infrastructure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Context is not static. It’s political, social, economic, and human. That’s where engineering judgment lives-and where AI struggles the most.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Real Role of a Software Engineer
&lt;/h3&gt;

&lt;p&gt;A software engineer is closer to a &lt;strong&gt;systems thinker&lt;/strong&gt; than a typist.&lt;/p&gt;

&lt;p&gt;They:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ask &lt;em&gt;why&lt;/em&gt; before &lt;em&gt;how&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Challenge requirements that don’t make sense&lt;/li&gt;
&lt;li&gt;Design for failure, not perfection&lt;/li&gt;
&lt;li&gt;Communicate trade-offs to non-technical stakeholders&lt;/li&gt;
&lt;li&gt;Take responsibility for outcomes, not just outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why senior engineers write less code than juniors-but create far more value.&lt;/p&gt;

&lt;h3&gt;
  
  
  What AI Actually Changes
&lt;/h3&gt;

&lt;p&gt;AI doesn’t eliminate software engineers. It &lt;strong&gt;raises the bar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Just like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Compilers didn’t eliminate programmers&lt;/li&gt;
&lt;li&gt;Frameworks didn’t eliminate engineers&lt;/li&gt;
&lt;li&gt;Cloud computing didn’t eliminate infrastructure thinking&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI removes low-level friction and exposes who actually understands systems.&lt;/p&gt;

&lt;p&gt;The future belongs to engineers who can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Think clearly&lt;/li&gt;
&lt;li&gt;Reason about systems&lt;/li&gt;
&lt;li&gt;Make sound decisions&lt;/li&gt;
&lt;li&gt;Use AI as a tool, not fear it as a replacement&lt;/li&gt;
&lt;/ul&gt;

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

&lt;p&gt;The first mistake was reducing software engineering to coding.&lt;br&gt;
The second mistake is assuming automation replaces thinking.&lt;/p&gt;

&lt;p&gt;AI will write more code.&lt;br&gt;
Humans will still decide &lt;strong&gt;what should exist, why it should exist, and whether it should exist at all&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That’s not going away anytime soon.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>tutorial</category>
      <category>beginners</category>
      <category>software</category>
    </item>
    <item>
      <title>Passing Props in React (How Components Talk to Each Other)</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Wed, 04 Feb 2026 06:50:00 +0000</pubDate>
      <link>https://dev.to/msnmongare/passing-props-in-react-how-components-talk-to-each-other-5654</link>
      <guid>https://dev.to/msnmongare/passing-props-in-react-how-components-talk-to-each-other-5654</guid>
      <description>&lt;h2&gt;
  
  
  Why Passing Props Exists
&lt;/h2&gt;

&lt;p&gt;In React:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components are &lt;strong&gt;isolated&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;One component cannot access another’s data directly&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So how do they communicate?&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;Props&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  What Are Props?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Props are inputs to a component.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Think of them like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Function parameters&lt;/li&gt;
&lt;li&gt;API request data&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Simple Example
&lt;/h2&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;Greeting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&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;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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Greeting&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"John"&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;
  
  
  What’s Happening?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;App&lt;/code&gt; sends data → &lt;code&gt;name="John"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Greeting&lt;/code&gt; receives it → &lt;code&gt;{ name }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;UI updates based on props&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Backend analogy:&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&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="s2"&gt;`Hello &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&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="nf"&gt;greeting&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&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;
  
  
  Props Are Read-Only
&lt;/h2&gt;

&lt;p&gt;❌ This is NOT allowed:&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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Mike&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;Props are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Immutable&lt;/li&gt;
&lt;li&gt;Owned by the parent&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If data must change → it belongs in &lt;strong&gt;state&lt;/strong&gt;, not props.&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Beginner Mistake
&lt;/h2&gt;

&lt;p&gt;Trying to store everything in one component.&lt;/p&gt;

&lt;p&gt;Correct mindset:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Components should &lt;strong&gt;receive data&lt;/strong&gt;, not own everything.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Props are how data &lt;strong&gt;flows downward&lt;/strong&gt; in React.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;No props → no real app.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
    </item>
    <item>
      <title>Lifting State Up in React (Sharing State the Right Way)</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Wed, 04 Feb 2026 06:50:00 +0000</pubDate>
      <link>https://dev.to/msnmongare/lifting-state-up-in-react-sharing-state-the-right-way-3i9d</link>
      <guid>https://dev.to/msnmongare/lifting-state-up-in-react-sharing-state-the-right-way-3i9d</guid>
      <description>&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Two components need the same data.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Login component logs in a user&lt;/li&gt;
&lt;li&gt;Dashboard component needs that user info&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If both manage their own state → chaos.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Lift State Up
&lt;/h2&gt;

&lt;p&gt;Move the state to the &lt;strong&gt;closest common parent&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Example
&lt;/h2&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;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="kc"&gt;null&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="nc"&gt;Login&lt;/span&gt; &lt;span class="na"&gt;setUser&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setUser&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;Dashboard&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&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;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;h2&gt;
  
  
  How This Works
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;App&lt;/code&gt; owns the state&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Login&lt;/code&gt; updates it&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Dashboard&lt;/code&gt; consumes it&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One source of truth.&lt;/p&gt;




&lt;h2&gt;
  
  
  Backend Analogy
&lt;/h2&gt;

&lt;p&gt;Think of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parent → service layer&lt;/li&gt;
&lt;li&gt;Children → controllers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Controllers don’t own data — services do.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Lift State
&lt;/h2&gt;

&lt;p&gt;Lift state when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Multiple components need the same data&lt;/li&gt;
&lt;li&gt;Data must stay in sync&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Warning Sign
&lt;/h2&gt;

&lt;p&gt;If you’re passing props through &lt;strong&gt;many layers&lt;/strong&gt;, stop.&lt;/p&gt;

&lt;p&gt;You’re about to need global state.&lt;/p&gt;




&lt;h2&gt;
  
  
  Key Takeaway
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Shared data should live &lt;strong&gt;above&lt;/strong&gt; the components that use it&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>javascript</category>
      <category>beginners</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Understanding `useContext` in React (A Beginner-Friendly Guide)</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Tue, 03 Feb 2026 13:33:16 +0000</pubDate>
      <link>https://dev.to/msnmongare/understanding-usecontext-in-react-a-beginner-friendly-guide-44dg</link>
      <guid>https://dev.to/msnmongare/understanding-usecontext-in-react-a-beginner-friendly-guide-44dg</guid>
      <description>&lt;p&gt;If you’re learning React, you’ll quickly run into this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“How do I share data between many components without passing props everywhere?”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That problem is exactly why &lt;strong&gt;&lt;code&gt;useContext&lt;/code&gt; exists&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. The Problem &lt;code&gt;useContext&lt;/code&gt; Solves
&lt;/h2&gt;

&lt;p&gt;Let’s start with the pain.&lt;/p&gt;

&lt;p&gt;Imagine this component tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App
 └── Layout
     └── Sidebar
         └── Profile
             └── Avatar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The logged-in user lives in &lt;code&gt;App&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Only &lt;code&gt;Avatar&lt;/code&gt; needs the user’s name&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Without context, you must pass props like 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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&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;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Layout&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&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;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Sidebar&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&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;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Profile&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&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;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Avatar&lt;/span&gt; &lt;span class="na"&gt;user&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&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;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Profile&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;Sidebar&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;Layout&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is called &lt;strong&gt;prop drilling&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why prop drilling is bad
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Components receive data they don’t need&lt;/li&gt;
&lt;li&gt;Code becomes noisy&lt;/li&gt;
&lt;li&gt;Refactoring is painful&lt;/li&gt;
&lt;li&gt;Bugs creep in easily&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  2. What Is Context (Plain English)
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context is a way to store data once and read it anywhere below.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In human terms:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Make this data global for part of the app.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Context does &lt;strong&gt;not&lt;/strong&gt; replace state.&lt;br&gt;
It just changes &lt;strong&gt;how state is shared&lt;/strong&gt;.&lt;/p&gt;


&lt;h2&gt;
  
  
  3. What Is &lt;code&gt;useContext&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useContext&lt;/code&gt; is the hook that lets a component &lt;strong&gt;read data from a Context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Think of it as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Give me the shared data without passing props.”&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  4. A Very Simple Example (No Complexity)
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Step 1: Create a Context
&lt;/h3&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;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="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="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;UserContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This creates a &lt;strong&gt;container&lt;/strong&gt; for shared data.&lt;/p&gt;


&lt;h3&gt;
  
  
  Step 2: Provide the Context (at the top)
&lt;/h3&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;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="nx"&gt;UserContext&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="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;John&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="nx"&gt;user&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;Dashboard&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;What’s happening:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;UserContext.Provider&lt;/code&gt; wraps your app&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;value={user}&lt;/code&gt; is the shared data&lt;/li&gt;
&lt;li&gt;Every component inside can access it&lt;/li&gt;
&lt;/ul&gt;


&lt;h3&gt;
  
  
  Step 3: Consume the Context
&lt;/h3&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;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="nx"&gt;UserContext&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;Dashboard&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;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;h1&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="p"&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;h1&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;p&gt;No props.&lt;br&gt;
No drilling.&lt;br&gt;
Just access.&lt;/p&gt;


&lt;h2&gt;
  
  
  5. Backend Mental Model (Very Important)
&lt;/h2&gt;

&lt;p&gt;Think of Context like:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Backend Concept&lt;/th&gt;
&lt;th&gt;React Context&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Config file&lt;/td&gt;
&lt;td&gt;Context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth middleware&lt;/td&gt;
&lt;td&gt;Provider&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Request access&lt;/td&gt;
&lt;td&gt;useContext&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Once data is in Context:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don’t pass it manually&lt;/li&gt;
&lt;li&gt;You just read it when needed&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  6. When Should You Use &lt;code&gt;useContext&lt;/code&gt;?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Good use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Logged-in user&lt;/li&gt;
&lt;li&gt;Theme (dark/light)&lt;/li&gt;
&lt;li&gt;Language&lt;/li&gt;
&lt;li&gt;App-wide settings&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Bad use cases
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Highly dynamic data (typing, counters)&lt;/li&gt;
&lt;li&gt;Large, frequently changing lists&lt;/li&gt;
&lt;li&gt;Complex business logic&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  7. Sharing State AND Actions (Common Pattern)
&lt;/h2&gt;

&lt;p&gt;Usually, you’ll share both:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data&lt;/li&gt;
&lt;li&gt;Functions to update the data
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&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;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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Then consume:&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;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;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is how login/logout works.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Why Context Is NOT a State Manager
&lt;/h2&gt;

&lt;p&gt;Important beginner truth:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Context does &lt;strong&gt;not&lt;/strong&gt; manage state.&lt;br&gt;
It only &lt;strong&gt;distributes&lt;/strong&gt; state.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You still need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;or another store&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Context is the &lt;strong&gt;delivery system&lt;/strong&gt;, not the engine.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Common Beginner Mistakes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  ❌ Using Context for everything
&lt;/h3&gt;

&lt;p&gt;This leads to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Performance issues&lt;/li&gt;
&lt;li&gt;Hard-to-track updates&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Putting too much logic in Context
&lt;/h3&gt;

&lt;p&gt;Keep it simple:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data&lt;/li&gt;
&lt;li&gt;Small helpers&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  ❌ Forgetting Provider
&lt;/h3&gt;

&lt;p&gt;If there’s no Provider, &lt;code&gt;useContext&lt;/code&gt; returns &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. &lt;code&gt;useContext&lt;/code&gt; vs Props (Quick Comparison)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Props&lt;/th&gt;
&lt;th&gt;useContext&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Explicit&lt;/td&gt;
&lt;td&gt;Implicit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Best for local data&lt;/td&gt;
&lt;td&gt;Best for shared data&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy to trace&lt;/td&gt;
&lt;td&gt;Can be hidden&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No setup&lt;/td&gt;
&lt;td&gt;Needs Provider&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  11. A Simple Rule to Remember
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If many components need the same data, and passing props feels annoying — use Context.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  12. Where &lt;code&gt;useContext&lt;/code&gt; Fits in Your Learning Path
&lt;/h2&gt;

&lt;p&gt;You should learn &lt;code&gt;useContext&lt;/code&gt; &lt;strong&gt;after&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Passing props&lt;/li&gt;
&lt;li&gt;Lifting state up&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And &lt;strong&gt;before&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Redux&lt;/li&gt;
&lt;li&gt;Zustand&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useContext&lt;/code&gt; solves prop drilling&lt;/li&gt;
&lt;li&gt;It lets components read shared data&lt;/li&gt;
&lt;li&gt;It works best for global, stable data&lt;/li&gt;
&lt;li&gt;It does not replace state management libraries&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once this clicks, React starts feeling &lt;strong&gt;clean and intentional&lt;/strong&gt;, not messy.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>react</category>
      <category>reactjsdevelopment</category>
    </item>
    <item>
      <title>Understanding `useEffect` in React: A Beginner-Friendly Guide</title>
      <dc:creator>Sospeter Mong'are</dc:creator>
      <pubDate>Tue, 03 Feb 2026 11:46:25 +0000</pubDate>
      <link>https://dev.to/msnmongare/understanding-useeffect-in-react-a-beginner-friendly-guide-4e3l</link>
      <guid>https://dev.to/msnmongare/understanding-useeffect-in-react-a-beginner-friendly-guide-4e3l</guid>
      <description>&lt;p&gt;If you’re new to React, one thing that often confuses beginners is &lt;strong&gt;when and why to use &lt;code&gt;useEffect&lt;/code&gt;&lt;/strong&gt;. Let’s break it down &lt;strong&gt;slowly&lt;/strong&gt;, so it makes perfect sense even if you’ve never done frontend before.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. What is &lt;code&gt;useEffect&lt;/code&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is a &lt;strong&gt;React Hook&lt;/strong&gt; that lets you perform &lt;strong&gt;side effects&lt;/strong&gt; in a component.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Side effects&lt;/strong&gt; are things your component does that are &lt;strong&gt;outside rendering the UI&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetching data from an API&lt;/li&gt;
&lt;li&gt;Logging to the console&lt;/li&gt;
&lt;li&gt;Setting timers (&lt;code&gt;setTimeout&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Interacting with browser APIs (like &lt;code&gt;localStorage&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In plain terms:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“useEffect is a way to tell React: do this action after the component appears on the page or when something changes.”&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. When do you actually need it?
&lt;/h2&gt;

&lt;p&gt;Think of &lt;code&gt;useEffect&lt;/code&gt; as &lt;strong&gt;React’s way of replacing old lifecycle methods&lt;/strong&gt; from class components:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Old React class method&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;useEffect&lt;/code&gt; equivalent&lt;/th&gt;
&lt;th&gt;Typical use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;componentDidMount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useEffect(() =&amp;gt; { ... }, [])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run once on page load&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;componentDidUpdate&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useEffect(() =&amp;gt; { ... }, [dependency])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Run when a value changes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;componentWillUnmount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useEffect(() =&amp;gt; { return () =&amp;gt; {...} }, [])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Clean up before component disappears&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h3&gt;
  
  
  2.1 Backend Analogy
&lt;/h3&gt;

&lt;p&gt;If React were a backend server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useEffect(() =&amp;gt; fetchData(), [])&lt;/code&gt; → “Call the database &lt;strong&gt;once when the request starts&lt;/strong&gt;”&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useEffect(() =&amp;gt; fetchData(), [userId])&lt;/code&gt; → “Call the database &lt;strong&gt;every time the userId changes&lt;/strong&gt;”&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it very intuitive if you already understand &lt;strong&gt;API calls and triggers&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. The Basic Syntax
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// code you want to run&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Breaking it down:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First argument:&lt;/strong&gt; A function containing the code you want to run (your “effect”)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Second argument:&lt;/strong&gt; An array of dependencies that tells React &lt;strong&gt;when&lt;/strong&gt; to run the effect&lt;/li&gt;
&lt;/ul&gt;




&lt;h3&gt;
  
  
  3.1 Dependency Array &lt;code&gt;[]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Empty array &lt;code&gt;[]&lt;/code&gt; → Run &lt;strong&gt;once&lt;/strong&gt;, after the component loads&lt;/li&gt;
&lt;li&gt;Example:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Component loaded!&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="p"&gt;[]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Think of it like &lt;code&gt;onPageLoad&lt;/code&gt;.&lt;/p&gt;




&lt;h3&gt;
  
  
  3.2 Dependencies &lt;code&gt;[value]&lt;/code&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Add values inside the array → Run &lt;strong&gt;every time one of these values changes&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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;`Count changed to: &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="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, the effect only runs &lt;strong&gt;when &lt;code&gt;count&lt;/code&gt; changes&lt;/strong&gt;.&lt;br&gt;
Backend analogy: “Re-fetch or re-run a query when this parameter changes.”&lt;/p&gt;


&lt;h3&gt;
  
  
  3.3 No Dependency Array
&lt;/h3&gt;

&lt;p&gt;If you &lt;strong&gt;don’t provide a dependency array&lt;/strong&gt;, the effect runs &lt;strong&gt;after every render&lt;/strong&gt;:&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Runs on every render!&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;p&gt;⚠️ Be careful — this can cause &lt;strong&gt;infinite loops&lt;/strong&gt; if you update state inside the effect.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. A Real Example: Fetching Groups on Page Load
&lt;/h2&gt;

&lt;p&gt;This is exactly like your &lt;code&gt;GroupList&lt;/code&gt; component:&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="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="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="s2"&gt;http://localhost:3000/groups&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="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Bearer TOKEN&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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="nf"&gt;setGroups&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;groups&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// empty array → run only once&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;API is called &lt;strong&gt;once&lt;/strong&gt; when component appears&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;groups&lt;/code&gt; state updates → React re-renders the UI automatically&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Cleanup Function (Optional but Important)
&lt;/h2&gt;

&lt;p&gt;Sometimes effects need cleanup, like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing event listeners&lt;/li&gt;
&lt;li&gt;Clearing timers&lt;/li&gt;
&lt;li&gt;Canceling subscriptions
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nf"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;timer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Tick&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// cleanup function&lt;/span&gt;
  &lt;span class="k"&gt;return &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;clearInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;timer&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;Think of it as &lt;strong&gt;undoing something before the component disappears&lt;/strong&gt;, similar to closing a DB connection.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Common Beginner Mistakes
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mistake&lt;/th&gt;
&lt;th&gt;Why It Happens&lt;/th&gt;
&lt;th&gt;How to Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forgetting &lt;code&gt;[]&lt;/code&gt; when effect should run once&lt;/td&gt;
&lt;td&gt;Effect runs on every render → infinite API calls&lt;/td&gt;
&lt;td&gt;Add empty dependency array &lt;code&gt;[]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Updating state without dependency&lt;/td&gt;
&lt;td&gt;Infinite loop: state changes → render → effect → state&lt;/td&gt;
&lt;td&gt;Include correct dependencies &lt;code&gt;[state]&lt;/code&gt; or move code to a button click&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Using &lt;code&gt;useEffect&lt;/code&gt; for user actions&lt;/td&gt;
&lt;td&gt;e.g., clicking a button should not run automatically&lt;/td&gt;
&lt;td&gt;Keep &lt;code&gt;useEffect&lt;/code&gt; for side effects, not triggers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  7. Golden Rules
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;useEffect&lt;/code&gt; = side effects, not user actions&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Empty array &lt;code&gt;[]&lt;/code&gt; = run once&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependencies &lt;code&gt;[value]&lt;/code&gt; = run when value changes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Return a cleanup function if needed&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Don’t use &lt;code&gt;useEffect&lt;/code&gt; to replace normal function calls triggered by buttons&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  8. Quick Mental Model (Backend-Friendly)
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Backend Concept&lt;/th&gt;
&lt;th&gt;React &lt;code&gt;useEffect&lt;/code&gt; Equivalent&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;API request on page load&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useEffect(() =&amp;gt; fetchData(), [])&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API request on parameter change&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useEffect(() =&amp;gt; fetchData(), [param])&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closing DB connection&lt;/td&gt;
&lt;td&gt;&lt;code&gt;return () =&amp;gt; cleanup()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  9. Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useEffect&lt;/code&gt; is &lt;strong&gt;React’s way of doing things after rendering&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fetching data&lt;/li&gt;
&lt;li&gt;Logging&lt;/li&gt;
&lt;li&gt;Timers or subscriptions&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Don’t use it for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Button clicks&lt;/li&gt;
&lt;li&gt;User input triggers (use event handlers instead)&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;✅ Once you understand &lt;code&gt;useEffect&lt;/code&gt;, &lt;strong&gt;React stops feeling magical&lt;/strong&gt; — it becomes predictable, just like backend logic:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load component → run effect&lt;/li&gt;
&lt;li&gt;Dependencies change → re-run effect&lt;/li&gt;
&lt;li&gt;Cleanup when leaving → prevent leaks&lt;/li&gt;
&lt;/ol&gt;

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