<?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: Nainik Mehta</title>
    <description>The latest articles on DEV Community by Nainik Mehta (@nainikmehta).</description>
    <link>https://dev.to/nainikmehta</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2447268%2F50173e95-5d7c-4576-b905-125bcab1c744.jpeg</url>
      <title>DEV Community: Nainik Mehta</title>
      <link>https://dev.to/nainikmehta</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nainikmehta"/>
    <language>en</language>
    <item>
      <title>Next.js 15: Why Server Actions are Replacing API Routes</title>
      <dc:creator>Nainik Mehta</dc:creator>
      <pubDate>Sat, 22 Aug 2026 07:31:07 +0000</pubDate>
      <link>https://dev.to/nainikmehta/nextjs-15-why-server-actions-are-replacing-api-routes-50ej</link>
      <guid>https://dev.to/nainikmehta/nextjs-15-why-server-actions-are-replacing-api-routes-50ej</guid>
      <description>&lt;h2&gt;
  
  
  The Shift in Full-Stack Architecture
&lt;/h2&gt;

&lt;p&gt;For years, the standard workflow for full-stack developers was rigid. If you wanted to update a user's profile, you followed a predictable, boilerplate-heavy path: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define an API route (&lt;code&gt;/api/user/update&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Implement the POST handler.&lt;/li&gt;
&lt;li&gt;Parse the request body.&lt;/li&gt;
&lt;li&gt;Validate types on the server.&lt;/li&gt;
&lt;li&gt;Hit the database.&lt;/li&gt;
&lt;li&gt;On the frontend, write a &lt;code&gt;fetch&lt;/code&gt; call or use a library like TanStack Query to manage loading states, caching, and error handling.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It felt like building two separate applications—a frontend and a backend—that just happened to communicate via HTTP.&lt;/p&gt;

&lt;p&gt;With &lt;strong&gt;Next.js Server Actions&lt;/strong&gt;, that wall is finally coming down. In Next.js 15, the "API folder" is becoming a relic of the past for internal application logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are Server Actions?
&lt;/h2&gt;

&lt;p&gt;A Server Action is an asynchronous function marked with the &lt;code&gt;'use server'&lt;/code&gt; directive. It runs exclusively on the server but is callable directly from your React components. &lt;/p&gt;

&lt;p&gt;When you call a Server Action, Next.js handles the RPC (Remote Procedure Call) boundary for you. You don't have to worry about defining URLs, manual &lt;code&gt;fetch&lt;/code&gt; calls, or managing JSON serialization. You simply import the function and invoke it.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Before and After
&lt;/h3&gt;

&lt;p&gt;Consider a simple profile update form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Old Way (REST API Route):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/user/update/route.ts&lt;/span&gt;
&lt;span class="k"&gt;export&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;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&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;body&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;req&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="c1"&gt;// Validate, update DB...&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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="na"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// app/profile/page.tsx&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="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;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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/api/user/update&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;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="c1"&gt;// Handle response, error states, etc.&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;The New Way (Server Action):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/actions/user.ts&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;updateProfile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormData&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Validate, update DB directly&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="nf"&gt;revalidatePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/profile&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="c1"&gt;// app/profile/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;updateProfile&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@/app/actions/user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProfileForm&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;form&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;updateProfile&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="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/form&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why This Changes Everything
&lt;/h2&gt;

&lt;p&gt;This isn't just about deleting files. It’s about a fundamental shift in the &lt;strong&gt;mental model&lt;/strong&gt; of full-stack development.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Reduced Cognitive Load
&lt;/h3&gt;

&lt;p&gt;When your data mutations are co-located with your UI, debugging becomes significantly faster. You aren't chasing a bug across three different files, two different protocols, and a middle-layer of API definitions. The logic is right where you need it.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Type Safety Across the Boundary
&lt;/h3&gt;

&lt;p&gt;Because Server Actions are just TypeScript functions, you get end-to-end type safety for free. If you change your database schema and update your action, TypeScript will immediately flag errors in your components. No more manual sync between frontend types and backend API contracts.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Automatic Integration
&lt;/h3&gt;

&lt;p&gt;Server Actions are built to work with Next.js caching. Using &lt;code&gt;revalidatePath&lt;/code&gt; or &lt;code&gt;revalidateTag&lt;/code&gt; inside an action automatically refreshes your UI data without needing manual state invalidation logic.&lt;/p&gt;

&lt;h2&gt;
  
  
  When Should You Still Use API Routes?
&lt;/h2&gt;

&lt;p&gt;While Server Actions are a game-changer for internal application logic, they are not a silver bullet. You should still reach for traditional API Routes (or Route Handlers) when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Public-facing APIs:&lt;/strong&gt; If you are building an API for third-party developers, mobile apps, or external integrations, you need a stable, documented REST or GraphQL contract.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Webhooks:&lt;/strong&gt; Services like Stripe or GitHub require a stable URL to send payloads.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Streaming/Long-running tasks:&lt;/strong&gt; If you need to handle long-running background jobs or custom streaming responses, Route Handlers provide the fine-grained control necessary.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;The future of full-stack development isn't about building &lt;em&gt;better&lt;/em&gt; APIs; it's about removing the need for them entirely for your internal application logic. By treating your backend as a set of functions rather than a set of endpoints, you can ship faster, reduce bugs, and focus on the user experience.&lt;/p&gt;

&lt;p&gt;Are you still building traditional REST endpoints for your Next.js apps, or have you fully moved to Server Actions? Let's discuss in the comments.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>react</category>
      <category>fullstack</category>
    </item>
    <item>
      <title>Are Custom Hooks Ruining Your React App Performance?</title>
      <dc:creator>Nainik Mehta</dc:creator>
      <pubDate>Sat, 22 Aug 2026 03:01:12 +0000</pubDate>
      <link>https://dev.to/nainikmehta/are-custom-hooks-ruining-your-react-app-performance-1o49</link>
      <guid>https://dev.to/nainikmehta/are-custom-hooks-ruining-your-react-app-performance-1o49</guid>
      <description>&lt;h2&gt;
  
  
  The Hidden Cost of "Clean" Code
&lt;/h2&gt;

&lt;p&gt;As React developers, we are taught to value clean, DRY (Don't Repeat Yourself) code. We see a component cluttered with 50 lines of state management and fetch logic, and our immediate instinct is to refactor it into a sleek, reusable custom hook like &lt;code&gt;useDashboardFilters()&lt;/code&gt;. It feels like a win: the parent component shrinks to a pristine 10 lines of JSX, and the logic is neatly tucked away.&lt;/p&gt;

&lt;p&gt;But this "clean" architecture can be a silent performance killer. While custom hooks are excellent for sharing logic, they do not isolate state. When you move state into a custom hook, you haven't hidden the performance impact—you've simply moved the source of the re-renders. If you aren't careful, your pursuit of clean code can lead to significant &lt;strong&gt;React custom hooks performance&lt;/strong&gt; issues that plague your users with laggy interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Hooks Trigger Re-renders
&lt;/h2&gt;

&lt;p&gt;To understand why this happens, we must remember that custom hooks are just functions. When a component calls a custom hook, it is essentially running that hook's code as part of its own render cycle. If that hook uses &lt;code&gt;useState&lt;/code&gt; or &lt;code&gt;useReducer&lt;/code&gt;, any update to that state will trigger a re-render of the &lt;em&gt;consuming&lt;/em&gt; component.&lt;/p&gt;

&lt;p&gt;This is the core of the problem: &lt;strong&gt;state changes in a hook propagate to the host component.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Imagine a &lt;code&gt;useDashboardFilters()&lt;/code&gt; hook that manages search queries, date ranges, and sorting. If you import this hook at the root of your dashboard shell, every keystroke in your search input updates the hook's state. Because that state lives "inside" the hook, the entire dashboard shell—including heavy data tables, sidebar navigation, and complex graph components—is forced to re-render on every single character typed. The input feels sluggish, and frame rates drop because the entire tree is re-evaluating.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Anti-Pattern: Over-Abstracting State
&lt;/h2&gt;

&lt;p&gt;We often fall into the trap of "lifting state up" into custom hooks prematurely. While this makes the code look cleaner, it often violates the principle of keeping state as close to the leaf nodes of your component tree as possible.&lt;/p&gt;

&lt;p&gt;Consider this simplified example of a problematic hook:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ❌ The performance trap: State is too high up&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useSearch&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="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="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt; &lt;span class="p"&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSearch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Re-renders the whole Dashboard on every keystroke&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;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&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;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HeavyDataTable&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; 
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;In this scenario, &lt;code&gt;HeavyDataTable&lt;/code&gt; re-renders every time the user types, even though it likely doesn't care about the intermediate keystrokes. The abstraction created an illusion of simplicity while hiding a massive performance bottleneck.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Optimize React Custom Hooks
&lt;/h2&gt;

&lt;p&gt;Improving &lt;strong&gt;React state management&lt;/strong&gt; doesn't mean abandoning custom hooks; it means changing how you structure them. Here are three strategies to keep your app performant:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Move State Down
&lt;/h3&gt;

&lt;p&gt;The most effective fix is to keep the state local to the component that actually needs it. Instead of forcing the dashboard shell to manage the search state, move the search input into its own component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ The fix: Isolate the state&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SearchInput&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;query&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setQuery&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{(&lt;/span&gt;&lt;span class="nx"&gt;e&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;setQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&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="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SearchInput&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HeavyDataTable&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&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;Now, typing in the search bar only re-renders the &lt;code&gt;SearchInput&lt;/code&gt; component. The &lt;code&gt;Dashboard&lt;/code&gt; and &lt;code&gt;HeavyDataTable&lt;/code&gt; remain untouched.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Memoize Return Values
&lt;/h3&gt;

&lt;p&gt;If your hook returns objects or functions, ensure they are stable. Returning a new object literal on every render will break &lt;code&gt;React.memo&lt;/code&gt; for any child component consuming that hook.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ Stable return values&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;useStableData&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="k"&gt;return&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="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="na"&gt;formatted&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="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Split Large Hooks
&lt;/h3&gt;

&lt;p&gt;Don't create "God hooks" that manage unrelated pieces of state. If a hook manages both user profile data and notification settings, any update to notifications will force components only interested in the profile to re-render. Split these into &lt;code&gt;useUserProfile&lt;/code&gt; and &lt;code&gt;useNotifications&lt;/code&gt; to ensure components only subscribe to the state they actually consume.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Performance Over "Cleanliness"
&lt;/h2&gt;

&lt;p&gt;Clean architecture is a goal, but runtime performance is the reality your users experience. Before you extract logic into a custom hook, ask yourself: &lt;em&gt;Does this component truly need to re-render when this state changes?&lt;/em&gt; If the answer is no, keep the state local. Only abstract logic when you genuinely need to share it, and always be mindful of how your state placement affects the React rendering lifecycle. By keeping your state focused and your hooks surgical, you can enjoy clean code without sacrificing the responsiveness of your application.",article_title:&lt;/p&gt;

</description>
      <category>react</category>
      <category>performance</category>
      <category>webdev</category>
      <category>hooks</category>
    </item>
    <item>
      <title>Building a React AI Chatbot with Vercel AI SDK v5</title>
      <dc:creator>Nainik Mehta</dc:creator>
      <pubDate>Fri, 21 Aug 2026 13:02:07 +0000</pubDate>
      <link>https://dev.to/nainikmehta/building-a-react-ai-chatbot-with-vercel-ai-sdk-v5-4e15</link>
      <guid>https://dev.to/nainikmehta/building-a-react-ai-chatbot-with-vercel-ai-sdk-v5-4e15</guid>
      <description>&lt;p&gt;Building a robust AI chatbot in React used to be a minefield of security vulnerabilities and performance bottlenecks. Many developers start by streaming raw text chunks directly from the frontend, inadvertently exposing API keys in their network tab or struggling with complex state management as they try to sync UI updates with LLM responses.&lt;/p&gt;

&lt;p&gt;The release of &lt;strong&gt;Vercel AI SDK v5&lt;/strong&gt; changes the game. By moving away from experimental patterns and embracing a stable, transport-based architecture, the latest iteration of the &lt;strong&gt;Vercel AI SDK React&lt;/strong&gt; integration provides a secure, type-safe, and highly performant way to build modern AI applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Security Trap: Why Frontend Streaming Fails
&lt;/h2&gt;

&lt;p&gt;The most common mistake when building a &lt;strong&gt;React AI chatbot&lt;/strong&gt; is handling API calls directly in the browser. When you initialize an LLM client in your &lt;code&gt;useEffect&lt;/code&gt; or event handlers, your secret API keys are bundled into the client-side code. Anyone inspecting your network requests can extract these credentials, leading to potential abuse and unexpected costs.&lt;/p&gt;

&lt;p&gt;Furthermore, manual streaming implementations often rely on &lt;code&gt;useState&lt;/code&gt; to buffer incoming chunks. As the LLM streams text, React triggers re-renders for every single chunk, leading to UI flickering and significant performance degradation—especially when dealing with complex data or tool calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Vercel AI SDK v5 Solves This
&lt;/h2&gt;

&lt;p&gt;Vercel AI SDK v5 introduces a redesigned &lt;code&gt;useChat&lt;/code&gt; hook and a robust streaming architecture that shifts the heavy lifting to the server. By leveraging &lt;strong&gt;Server-Sent Events (SSE)&lt;/strong&gt;, the SDK ensures that your API keys remain securely on the server-side, while your frontend only receives the processed, sanitized output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Architectural Improvements:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Transport-Based Architecture:&lt;/strong&gt; The SDK now uses a modular transport system, making it easier to integrate with different backend setups while maintaining security.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Typed Tool Invocations:&lt;/strong&gt; Tool calls are no longer generic strings. They are fully typed parts of the message stream, ensuring that your frontend knows exactly how to render them.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Decoupled State Management:&lt;/strong&gt; The &lt;code&gt;useChat&lt;/code&gt; hook no longer manages input state internally, giving you more control over your UI and easier integration with state management libraries like Zustand or Redux.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation: A Secure Chatbot with &lt;code&gt;useChat&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;To get started, you need to separate your concerns: handle the LLM interaction on the server using &lt;code&gt;streamText&lt;/code&gt; and render the interface on the client using &lt;code&gt;useChat&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Server-Side: &lt;code&gt;streamText&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Your API route (e.g., &lt;code&gt;app/api/chat/route.ts&lt;/code&gt;) handles the LLM logic securely.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;streamText&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;openai&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ai-sdk/openai&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&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;messages&lt;/span&gt; &lt;span class="p"&gt;}&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;req&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="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="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;streamText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;openai&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gpt-4o&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Define your tools here&lt;/span&gt;
      &lt;span class="na"&gt;getWeather&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Get weather for a location&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="na"&gt;execute&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;location&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="cm"&gt;/* ... */&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toDataStreamResponse&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Client-Side: &lt;code&gt;useChat&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;In your React component, you simply call the &lt;code&gt;useChat&lt;/code&gt; hook. The SDK handles the streaming, message history, and tool invocation automatically.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useChat&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@ai-sdk/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Chat&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;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;handleSubmit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useChat&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;role&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* Render tool parts here */&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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSubmit&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&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;input&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setInput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&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;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Send&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&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;h2&gt;
  
  
  Moving Beyond Text: Handling Tools
&lt;/h2&gt;

&lt;p&gt;One of the most powerful features of the Vercel AI SDK is how it handles tool calls. Instead of parsing raw text to detect a function call, the SDK streams structured data parts. When the model invokes a tool, the &lt;code&gt;useChat&lt;/code&gt; hook receives a typed tool invocation that your UI can respond to immediately.&lt;/p&gt;

&lt;p&gt;By using the &lt;code&gt;onToolCall&lt;/code&gt; callback and &lt;code&gt;addToolOutput&lt;/code&gt; helper, you can create interactive experiences—like rendering a calendar component or a weather widget—directly inside your chat interface without the performance overhead of manual state synchronization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you are still manually parsing streams or exposing keys in your frontend config, you are building on shaky ground. Vercel AI SDK v5 provides the primitives you need to build professional, production-grade AI applications. By leveraging the secure &lt;code&gt;streamText&lt;/code&gt; and &lt;code&gt;useChat&lt;/code&gt; flow, you can focus on building delightful user experiences while the SDK handles the complexity of AI engineering.&lt;/p&gt;

&lt;p&gt;Ready to upgrade? Dive into the &lt;a href="https://ai-sdk.dev" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; and start building more secure, reactive AI interfaces today.&lt;/p&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
      <category>ai</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Next.js Server Actions vs Route Handlers: When to Use Each</title>
      <dc:creator>Nainik Mehta</dc:creator>
      <pubDate>Fri, 21 Aug 2026 10:30:02 +0000</pubDate>
      <link>https://dev.to/nainikmehta/nextjs-server-actions-vs-route-handlers-when-to-use-each-22c7</link>
      <guid>https://dev.to/nainikmehta/nextjs-server-actions-vs-route-handlers-when-to-use-each-22c7</guid>
      <description>&lt;p&gt;Are you still manually writing &lt;code&gt;fetch('/api/user')&lt;/code&gt; boilerplate for every simple form in your Next.js application? If so, you are likely over-engineering your codebase.&lt;/p&gt;

&lt;p&gt;Since the introduction of the App Router, Next.js has provided two powerful ways to handle server-side logic: &lt;strong&gt;Server Actions&lt;/strong&gt; and &lt;strong&gt;Route Handlers&lt;/strong&gt;. While both run on the server, they serve fundamentally different purposes. Choosing the wrong one can lead to bloated code, unnecessary complexity, and even security pitfalls.&lt;/p&gt;

&lt;p&gt;The good news is that the decision isn't difficult if you follow one core rule.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 1-Rule Decision Guide
&lt;/h2&gt;

&lt;p&gt;When deciding between Next.js Server Actions vs Route Handlers, ask yourself this question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Is this request triggered by a user action inside my React UI, or is it an external system/public integration calling my application?"&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;If it's a UI action:&lt;/strong&gt; Use &lt;strong&gt;Server Actions&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;If it's an external client:&lt;/strong&gt; Use &lt;strong&gt;Route Handlers&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This simple distinction keeps your code clean, type-safe, and performant by matching the tool to the intended consumer.&lt;/p&gt;




&lt;h2&gt;
  
  
  When to Use Server Actions
&lt;/h2&gt;

&lt;p&gt;Server Actions are designed for mutations triggered directly from your React components. They act as an RPC (Remote Procedure Call) mechanism, allowing you to call server-side functions as if they were local, without needing to manually define an API endpoint or write client-side &lt;code&gt;fetch&lt;/code&gt; calls.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why they win for UI mutations:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Reduced Boilerplate:&lt;/strong&gt; No need to manage &lt;code&gt;useState&lt;/code&gt; for loading/error states, no manual &lt;code&gt;fetch&lt;/code&gt; calls, and no manual API route serialization.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Type Safety:&lt;/strong&gt; You get end-to-end type safety from your database to your form.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Progressive Enhancement:&lt;/strong&gt; Forms using Server Actions can work even before JavaScript hydrates on the client.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Tight Integration:&lt;/strong&gt; They trigger React Server Component (RSC) re-renders, allowing your UI to update immediately after a mutation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Concrete Example: Form Submission
&lt;/h3&gt;

&lt;p&gt;Instead of creating an API route, parsing the body, and managing client-side state, you simply pass a function to the &lt;code&gt;action&lt;/code&gt; attribute:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/actions.ts&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;z&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;zod&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;onboardUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;FormData&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;schema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;object&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;z&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;email&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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;formData&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

  &lt;span class="c1"&gt;// Perform database mutation&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

  &lt;span class="c1"&gt;// Revalidate the page to show new data&lt;/span&gt;
  &lt;span class="nf"&gt;revalidatePath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/dashboard&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="c1"&gt;// app/components/OnboardingForm.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;OnboardingForm&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;form&lt;/span&gt; &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onboardUser&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&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;"email"&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"email"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;form&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;h2&gt;
  
  
  When to Use Route Handlers
&lt;/h2&gt;

&lt;p&gt;Route Handlers are the App Router's equivalent of traditional API routes. They provide a stable, public HTTP interface. They are not tied to your React UI lifecycle, which makes them the correct choice for anything that needs to be accessed by a non-React caller.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use Route Handlers for:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Webhooks:&lt;/strong&gt; Services like Stripe or GitHub need to POST to a stable, public URL.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Public APIs:&lt;/strong&gt; If you are exposing data to mobile apps, browser extensions, or third-party developers.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Custom Responses:&lt;/strong&gt; If you need to return non-JSON data (e.g., RSS feeds, XML, or file streams).&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Cross-Origin Requests:&lt;/strong&gt; When you need full control over CORS headers.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Concrete Example: Stripe Webhook
&lt;/h3&gt;

&lt;p&gt;Because Stripe's servers are invoking your endpoint—not your React UI—a Server Action is the wrong tool. You need a stable HTTP endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/api/webhooks/stripe/route.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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;next/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;POST&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Request&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;body&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;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;text&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;signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stripe-signature&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Verify signature and process event&lt;/span&gt;
  &lt;span class="c1"&gt;// ...&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;NextResponse&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="na"&gt;received&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  The Pitfalls of Over-Engineering
&lt;/h2&gt;

&lt;p&gt;A common mistake is trying to use Server Actions as a public API. While they are powerful, they are not intended to be a replacement for RESTful endpoints.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;URL Stability:&lt;/strong&gt; Server Action URLs are generated by the framework and can change between deployments. Never document them for external developers.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Concurrency:&lt;/strong&gt; Server Actions are designed for UI-driven mutations and are often executed sequentially to maintain React state consistency. If you need high-concurrency, parallel API calls, use Route Handlers.&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Security:&lt;/strong&gt; Just because a Server Action is imported in a component doesn't mean it's secure. Always validate inputs and check authentication inside the action, just as you would with a Route Handler.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Next.js Server Actions and Route Handlers are not competing technologies; they are complementary tools for different layers of your application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Server Actions&lt;/strong&gt; are for your &lt;strong&gt;UI&lt;/strong&gt;. They are tightly coupled to your React components and simplify internal mutations.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Route Handlers&lt;/strong&gt; are your &lt;strong&gt;API&lt;/strong&gt;. They are for external clients, webhooks, and any integration that requires a stable HTTP contract.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By keeping this distinction clear, you avoid the "leaky abstraction" trap and ensure your codebase remains maintainable as your project scales. Stop writing manual &lt;code&gt;fetch&lt;/code&gt; boilerplate for your forms—embrace the Server Action pattern for your UI, and reserve Route Handlers for the public-facing edges of your system.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>typescript</category>
      <category>webdev</category>
    </item>
    <item>
      <title>All About Axios…🥳</title>
      <dc:creator>Nainik Mehta</dc:creator>
      <pubDate>Sat, 23 Nov 2024 07:40:16 +0000</pubDate>
      <link>https://dev.to/nainikmehta/all-about-axios-223m</link>
      <guid>https://dev.to/nainikmehta/all-about-axios-223m</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg61ges09q2h1tgm1ncn4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg61ges09q2h1tgm1ncn4.png" alt="Axios" width="799" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Axios is a popular JavaScript library that serves as a powerful HTTP client for making asynchronous HTTP requests in the browser and Node.js. It provides an easy-to-use interface and supports various features such as promise-based requests, interceptors for request and response handling, and the ability to cancel requests. Axios simplifies the process of sending HTTP requests and handling responses, making it a preferred choice for many developers for tasks like fetching data from APIs, interacting with servers, and managing HTTP requests and responses in web applications. Its flexibility and comprehensive functionality make it a valuable tool for building robust and efficient applications that rely on network requests.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;HTTP Interceptors&amp;nbsp;:&lt;/strong&gt;&lt;br&gt;
HTTP interceptors allow us to check or modify all the incoming or outgoing HTTP requests in our application. We can use them if we want to apply something like an authorization header to all the requests. Let's see how we can implement it using Axios.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Getting started with Axios&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To install Axios in your project, you can use either npm (Node Package Manager) or Yarn (a package manager developed by Facebook). Both npm and Yarn allow you to manage and install JavaScript packages, including Axios. Here's how you can install Axios using npm or Yarn:&lt;/p&gt;
&lt;h2&gt;
  
  
  &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0akh6c014f7jhpsc75kn.png" alt="Install Axios" width="799" height="515"&gt;
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Axios Request Interceptor&amp;nbsp;:&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see how we can use Axios to setup request interceptor that will run before a request is made.&lt;br&gt;
&lt;/p&gt;

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

/* The code `axios.interceptors.request.use((config) =&amp;gt; { ... })` is creating an interceptor for Axios
requests. */
axios.interceptors.request.use((config) =&amp;gt; {
  // Log to print that request is intiated..
  console.log('Request was sent');

  // Data that can be keep track of which are sent in request
  console.log(`[${config.method}] ${config.url}`);
  console.log(`Headers :`);
  console.log(config.headers);
  console.log(`Params : `);
  console.log(config.params);
  console.log(`Data : `);
  console.log(config.data);

  return config;
});

const fetchQuotes = async () =&amp;gt; {
  try {
    const res = await axios.get(`https://type.fit/api/quotes`);
  } catch (error) {
    console.log(error);
  }
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Setting Request Headers :&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can use request interceptors to set default HTTP headers that we want to send in every request.&lt;/p&gt;

&lt;p&gt;Using request interceptors in Axios allows you to intercept outgoing requests before they are sent to the server. This feature is particularly useful for setting default configurations, headers, or any other properties that you want to apply to every request in your application. Here’s how you can use request interceptors to set default HTTP headers:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxqt1uq68grtmrmkc0ut.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftxqt1uq68grtmrmkc0ut.png" alt="Request Interceptors" width="800" height="327"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;em&gt;Response Interceptor :&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Similarly, we can also setup a response interceptor with Axios that will execute whenever we receive API response.&lt;/p&gt;

&lt;p&gt;Setting up a response interceptor with Axios allows you to intercept responses before they are handled by the then() or catch() methods. This feature is useful for globally handling errors, modifying the response data, or performing any other operations you require. Here's how you can set up a response interceptor with Axios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Axios response interceptor setup
axios.interceptors.response.use(
  (response) =&amp;gt; {
    // Handle successful responses
    console.log('Response received:', response.data);
    return response;
  },
  (error) =&amp;gt; {
    // Handle response errors
    console.error('Error encountered:', error);
    return Promise.reject(error);
  }
);

// Make a sample GET request
axios.get('https://jsonplaceholder.typicode.com/posts/1')
  .then((response) =&amp;gt; {
    console.log('Response data:', response.data);
  })
  .catch((error) =&amp;gt; {
    console.error('Error fetching data:', error);
  });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also, please feel free to share your own tips in the comments. 🧐&lt;/p&gt;

&lt;p&gt;👇 You can find and connect with me over 👇&lt;br&gt;
&lt;a href="https://www.facebook.com/nainikmehta.nainikmehta/" rel="noopener noreferrer"&gt;Facebook&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.linkedin.com/in/nainik-mehta-25nk12/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
&lt;a href="https://x.com/Nainik25" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt;&lt;br&gt;
&lt;a href="https://github.com/Nainik2509/" rel="noopener noreferrer"&gt;Github&lt;/a&gt;&lt;br&gt;
Happy Coding and keep exploring!&lt;/p&gt;

</description>
      <category>axios</category>
      <category>javascript</category>
      <category>fullstack</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
