<?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: ReactChallenges</title>
    <description>The latest articles on DEV Community by ReactChallenges (@reactchallenges).</description>
    <link>https://dev.to/reactchallenges</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%2F854942%2Fe450946a-3098-4715-8d06-0892ab9ac221.png</url>
      <title>DEV Community: ReactChallenges</title>
      <link>https://dev.to/reactchallenges</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/reactchallenges"/>
    <language>en</language>
    <item>
      <title>Context API vs Redux</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Sun, 20 Sep 2026 11:36:50 +0000</pubDate>
      <link>https://dev.to/reactchallenges/context-api-vs-redux-3o5e</link>
      <guid>https://dev.to/reactchallenges/context-api-vs-redux-3o5e</guid>
      <description>&lt;p&gt;The question is usually framed as "which one is better", but that's the wrong question. Context and Redux do different jobs. The important part is understanding how each one updates its consumers.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Try it in practice: &lt;a href="https://www.reactchallenges.com/challenges/shopping-cart" rel="noopener noreferrer"&gt;Shopping Cart with Context&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What Context actually does
&lt;/h2&gt;

&lt;p&gt;Context lets a component read and subscribe to a value without threading it down through props. The context object itself does not hold data; it only describes what can be provided and read. To make the value change, you pair the provider with &lt;code&gt;useState&lt;/code&gt; or &lt;code&gt;useReducer&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="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="s2"&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="s2"&gt;light&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;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;theme&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key detail, from the React docs: when the value you pass to a provider changes, React re-renders every component that reads that context. It compares the old and new values with &lt;code&gt;Object.is&lt;/code&gt;. There are no selectors, so you can't subscribe to just one field of the value.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Redux adds
&lt;/h2&gt;

&lt;p&gt;Redux is a centralized store with a single flow: action, reducer, store. Around that flow you get middleware, Redux DevTools, and an action history, so you can answer "when did this slice change and where did the data come from?".&lt;/p&gt;

&lt;p&gt;Its real advantage over Context is &lt;code&gt;useSelector&lt;/code&gt;. A component subscribes to the result it selects, not to the whole store:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;count&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="p"&gt;)&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;cart&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;length&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;theme&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="p"&gt;)&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;theme&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change &lt;code&gt;cart&lt;/code&gt; and the component reading &lt;code&gt;theme&lt;/code&gt; does not re-render. With Context, it would.&lt;/p&gt;

&lt;h2&gt;
  
  
  The re-render difference
&lt;/h2&gt;

&lt;p&gt;A Context subscription is to the context value as a whole, not to individual fields. Put &lt;code&gt;{ user, cart, theme }&lt;/code&gt; in a single context and changing &lt;code&gt;cart&lt;/code&gt; re-renders the component that only reads &lt;code&gt;theme&lt;/code&gt; too. You can fix this by splitting into multiple contexts and memoizing values, but that's work you do by hand. Redux gives you granular subscriptions through selectors.&lt;/p&gt;

&lt;h2&gt;
  
  
  When to use each
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt; for simple shared values with few consumers: theme, locale, current user, and state scoped to one feature. Zero dependencies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Redux&lt;/strong&gt; when shared client state gets large, is used in many places, or has update logic that's getting complex. It also helps when you need to inspect how state changes over time with Redux DevTools.&lt;/p&gt;

&lt;p&gt;Data fetched from an API is server state and belongs in SWR or React Query, not in either of these.&lt;/p&gt;

&lt;h2&gt;
  
  
  A real example: the shopping cart
&lt;/h2&gt;

&lt;p&gt;A cart with a few items, a header badge, and a checkout button is fine in Context.&lt;/p&gt;

&lt;p&gt;Watch what happens as it grows: a coupon field, a quantity stepper, a "save for later" list. Now items, coupon, and saved share one context. Updating items re-renders the coupon and saved consumers too. Put the coupon draft in that same context and every keystroke re-renders the header badge.&lt;/p&gt;

&lt;p&gt;That's where selectors earn their keep: components can subscribe to different slices of state independently, and a component re-renders only when the piece it reads changes. Redux DevTools and action history are the bonus on top.&lt;/p&gt;

&lt;p&gt;Start with Context. Reach for a store when the state and its consumers get complex enough to justify it, not before.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Build both and compare: &lt;a href="https://www.reactchallenges.com/challenges/shopping-cart-with-redux" rel="noopener noreferrer"&gt;Shopping Cart with Redux&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>redux</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Command Palette</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 16 Sep 2026 10:08:15 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-command-palette-24jn</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-command-palette-24jn</guid>
      <description>&lt;p&gt;Search bars are fine until someone hits Cmd/Ctrl+K. A command palette replaces hunting through menus with a keyboard-first layer that filters as you type — and building one forces you to combine global keyboard handling, focus management and correct ARIA semantics in a single component.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Build a keyboard-driven command palette (Cmd/Ctrl+K) with fuzzy filtering, arrow-key navigation, a focus trap and proper combobox/listbox semantics.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/command-palette" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/command-palette&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The palette is hidden on first render.&lt;/li&gt;
&lt;li&gt;Clicking the trigger opens the palette.&lt;/li&gt;
&lt;li&gt;Pressing Cmd/Ctrl+K opens the palette, and pressing it again closes it.&lt;/li&gt;
&lt;li&gt;Pressing Escape closes the palette.&lt;/li&gt;
&lt;li&gt;Clicking the backdrop closes the palette, while clicking inside the panel keeps it open.&lt;/li&gt;
&lt;li&gt;When the palette opens, the search input receives focus and is empty.&lt;/li&gt;
&lt;li&gt;The palette lists every command.&lt;/li&gt;
&lt;li&gt;Typing filters the commands by fuzzy match: every character of the query must appear in the label in order, ignoring case.&lt;/li&gt;
&lt;li&gt;When nothing matches, show &lt;code&gt;No results for "&amp;lt;query&amp;gt;"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Clearing the query restores the full list.&lt;/li&gt;
&lt;li&gt;The first command is highlighted when the palette opens and whenever the query changes.&lt;/li&gt;
&lt;li&gt;ArrowDown moves the highlight to the next command, wrapping from the last one to the first.&lt;/li&gt;
&lt;li&gt;ArrowUp moves the highlight to the previous command, wrapping from the first one to the last.&lt;/li&gt;
&lt;li&gt;Enter executes the highlighted command and closes the palette.&lt;/li&gt;
&lt;li&gt;Clicking a command executes it and closes the palette.&lt;/li&gt;
&lt;li&gt;Executing a command sets the &lt;code&gt;Last action&lt;/code&gt; text to that command's label.&lt;/li&gt;
&lt;li&gt;While the palette is open, focus stays inside it when pressing Tab.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Open and close from a single &lt;code&gt;window&lt;/code&gt; &lt;code&gt;keydown&lt;/code&gt; listener for Cmd/Ctrl+K and Escape, and call &lt;code&gt;preventDefault()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Filter by subsequence, not &lt;code&gt;includes&lt;/code&gt; ("gch" matches "Go to Challenges"), and reset &lt;code&gt;activeIndex&lt;/code&gt; when the query changes.&lt;/li&gt;
&lt;li&gt;Focus the input on open and keep focus trapped inside the panel by listening for &lt;code&gt;focusin&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;keeps the palette hidden on first render&lt;/li&gt;
&lt;li&gt;opens the palette when the trigger is clicked&lt;/li&gt;
&lt;li&gt;opens the palette with Cmd/Ctrl+K&lt;/li&gt;
&lt;li&gt;focuses the search input when opened&lt;/li&gt;
&lt;li&gt;closes the palette when the shortcut is pressed again&lt;/li&gt;
&lt;li&gt;closes the palette on Escape&lt;/li&gt;
&lt;li&gt;closes the palette when the backdrop is clicked&lt;/li&gt;
&lt;li&gt;keeps the palette open when clicking inside the panel&lt;/li&gt;
&lt;li&gt;renders every command&lt;/li&gt;
&lt;li&gt;filters commands as the user types&lt;/li&gt;
&lt;li&gt;matches non-contiguous characters&lt;/li&gt;
&lt;li&gt;is case-insensitive&lt;/li&gt;
&lt;li&gt;shows a no-results message when nothing matches&lt;/li&gt;
&lt;li&gt;restores the full list when the query is cleared&lt;/li&gt;
&lt;li&gt;clears the query when the palette is reopened&lt;/li&gt;
&lt;li&gt;highlights the first command by default&lt;/li&gt;
&lt;li&gt;moves the highlight down with ArrowDown&lt;/li&gt;
&lt;li&gt;wraps from the first to the last with ArrowUp&lt;/li&gt;
&lt;li&gt;wraps from the last to the first with ArrowDown&lt;/li&gt;
&lt;li&gt;resets the highlight when the query changes&lt;/li&gt;
&lt;li&gt;executes the highlighted command with Enter&lt;/li&gt;
&lt;li&gt;executes a command when clicked&lt;/li&gt;
&lt;li&gt;traps focus inside the palette on Tab&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you want to practice keyboard-driven UI the way real apps do it, this challenge gives you the full loop: open, filter, navigate, execute and trap focus — with 23 tests to keep you honest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/command-palette" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>5 common TypeScript interview questions</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Thu, 10 Sep 2026 09:40:33 +0000</pubDate>
      <link>https://dev.to/reactchallenges/5-common-typescript-interview-questions-10jb</link>
      <guid>https://dev.to/reactchallenges/5-common-typescript-interview-questions-10jb</guid>
      <description>&lt;p&gt;These five questions show up in almost every TypeScript interview. They're not tricky syntax puzzles. They test whether you understand the type system well enough to use it on purpose instead of just making the compiler happy.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;any&lt;/code&gt; vs &lt;code&gt;unknown&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;any&lt;/code&gt; turns type checking off. Once a value is &lt;code&gt;any&lt;/code&gt;, TypeScript stops protecting you and mistakes slip through until runtime. &lt;code&gt;unknown&lt;/code&gt; is the safe counterpart: it can hold anything, but you must narrow it before using it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&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="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅ no error&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;thisDoesNotExist&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅ no error either 💀&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;hello&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ❌ 'u' is of type 'unknown'&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;u&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&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;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// ✅ narrowed to string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reach for &lt;code&gt;unknown&lt;/code&gt; when the type is genuinely unknown, like API responses, &lt;code&gt;JSON.parse&lt;/code&gt;, or &lt;code&gt;catch&lt;/code&gt; variables, and never reach for &lt;code&gt;any&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;code&gt;interface&lt;/code&gt; vs &lt;code&gt;type&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Both describe object shapes and are mostly interchangeable. The real differences are what each one can express.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;interface&lt;/code&gt; supports &lt;strong&gt;declaration merging&lt;/strong&gt;; &lt;code&gt;type&lt;/code&gt; doesn't.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;type&lt;/code&gt; can express unions, intersections, tuples, and primitives; &lt;code&gt;interface&lt;/code&gt; only describes object-like shapes.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;interface&lt;/code&gt; extends with &lt;code&gt;extends&lt;/code&gt;; &lt;code&gt;type&lt;/code&gt; composes with &lt;code&gt;&amp;amp;&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// merged: { name: string; age: number }&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// only possible with type&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Declaration merging cuts both ways: it lets libraries augment existing types (like extending &lt;code&gt;Window&lt;/code&gt;), but it can also merge a typo into a valid type. A common convention is &lt;code&gt;interface&lt;/code&gt; for object APIs and &lt;code&gt;type&lt;/code&gt; for unions and computed types.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generics
&lt;/h2&gt;

&lt;p&gt;Generics let you write code that works with many types while preserving the relationship between input and output. Without them you'd duplicate the function per type or fall back to &lt;code&gt;any&lt;/code&gt; and lose the return type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;items&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="kc"&gt;undefined&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;items&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&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;first&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="c1"&gt;// number | undefined&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="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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="s2"&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;// string | undefined&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can constrain them when you need to rely on some structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;getProperty&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;K&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="kr"&gt;keyof&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;obj&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;key&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;T&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="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&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;key&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Alice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;getProperty&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="s2"&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;// ✅ string&lt;/span&gt;
&lt;span class="nf"&gt;getProperty&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="s2"&gt;age&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// ❌ "age" is not assignable to keyof typeof user&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The definition is easy to recite. The interview signal is being able to show a case where a generic removed duplication or a lost type.&lt;/p&gt;

&lt;h2&gt;
  
  
  Utility types
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;Partial&lt;/code&gt;, &lt;code&gt;Pick&lt;/code&gt;, &lt;code&gt;Omit&lt;/code&gt;, and &lt;code&gt;Record&lt;/code&gt; are built-in generics. They're not magic, but &lt;strong&gt;mapped types&lt;/strong&gt; that transform an existing type into a new one.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;email&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;PartialUser&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// every property optional&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserPreview&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Pick&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// only id and name&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserWithoutEmail&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Omit&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;User&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// everything except email&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UsersById&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;User&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;// { [key: string]: User }&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Under the hood, &lt;code&gt;Partial&lt;/code&gt; is roughly this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nb"&gt;Partial&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="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;K&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kr"&gt;keyof&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="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="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Knowing the mapping is what separates "I know they exist" from "I know how to build my own".&lt;/p&gt;

&lt;h2&gt;
  
  
  Type guards
&lt;/h2&gt;

&lt;p&gt;A type guard is an expression that gives TypeScript information it can use to &lt;strong&gt;narrow&lt;/strong&gt; a broader type into a more specific one within a block. Common narrowing checks include &lt;code&gt;typeof&lt;/code&gt;, &lt;code&gt;instanceof&lt;/code&gt;, &lt;code&gt;in&lt;/code&gt;, and equality checks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;format&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="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kr"&gt;number&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="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;string&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;return&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;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// string&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;value&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;// number&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you want to reuse a check across your code, wrap it in a named type guard using a &lt;strong&gt;type predicate&lt;/strong&gt; (&lt;code&gt;x is T&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;meow&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="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Dog&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bark&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="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;isCat&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;Cat&lt;/span&gt; &lt;span class="o"&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;animal&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;Cat&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;meow&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;animal&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now TypeScript can narrow the type when you call the guard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;speak&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;Cat&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;Dog&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="nf"&gt;isCat&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="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="nf"&gt;meow&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Cat&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="nx"&gt;animal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;bark&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Dog&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;animal is Cat&lt;/code&gt; return type is a contract: TypeScript trusts it and narrows &lt;code&gt;animal&lt;/code&gt; to &lt;code&gt;Cat&lt;/code&gt; when the function returns &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means the logic inside the guard is your responsibility. If the predicate is wrong, TypeScript won't catch the resulting bug.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>javascript</category>
      <category>react</category>
      <category>programming</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Infinite Scroll</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 09 Sep 2026 09:53:24 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-infinite-scroll-1mi2</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-infinite-scroll-1mi2</guid>
      <description>&lt;p&gt;"Load more" buttons are the easy way out. Real feeds — Twitter, Instagram, your chat app — load the next page the moment you scroll near the bottom. That magic is the &lt;strong&gt;Intersection Observer API&lt;/strong&gt;, and it's much cleaner than the old scroll-listener + throttle dance.&lt;/p&gt;

&lt;p&gt;This challenge gets you building an infinite scroll list of &lt;strong&gt;Rick &amp;amp; Morty characters&lt;/strong&gt; with React 19's Suspense-driven &lt;code&gt;use()&lt;/code&gt; fetching already in place. Your job: make the next page fetch itself.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Build an infinite scroll list of Rick and Morty characters using the &lt;strong&gt;Intersection Observer API&lt;/strong&gt; — the next page is fetched automatically when a sentinel element enters the viewport, building on an existing &lt;code&gt;use()&lt;/code&gt; + Suspense data-fetching setup.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/infinite-scroll" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/infinite-scroll&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Keep the starter's &lt;code&gt;use()&lt;/code&gt; + Suspense first-page fetch as the starting point&lt;/li&gt;
&lt;li&gt;Follow the API pagination and read the next page URL from &lt;code&gt;data.info.next&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Load the next page automatically when the user scrolls to the bottom — no button&lt;/li&gt;
&lt;li&gt;Trigger the load from a sentinel element observed by the Intersection Observer&lt;/li&gt;
&lt;li&gt;Append new characters to the existing list instead of replacing them&lt;/li&gt;
&lt;li&gt;Show a loading indicator while the next page is being fetched&lt;/li&gt;
&lt;li&gt;Hide the loading indicator once the page finishes loading&lt;/li&gt;
&lt;li&gt;Show an end-of-list message when there are no more pages&lt;/li&gt;
&lt;li&gt;Stop fetching once the end is reached — no requests when &lt;code&gt;info.next&lt;/code&gt; is &lt;code&gt;null&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Disconnect the observer when the component unmounts&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;App&lt;/code&gt; is fully wired: title, layout, and the Suspense fallback are done — all your work happens inside &lt;code&gt;Characters()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The components file is read-only, and the API follows the classic &lt;code&gt;{ info: { next, prev }, results: [...] }&lt;/code&gt; Rick &amp;amp; Morty response shape.&lt;/li&gt;
&lt;li&gt;Watch out: a couple of tests pass with the starter code simply because nothing fetches yet — they only start validating real behavior once your observer is in place.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;renders the app title&lt;/li&gt;
&lt;li&gt;shows skeleton while loading&lt;/li&gt;
&lt;li&gt;renders first-page characters after loading&lt;/li&gt;
&lt;li&gt;observes the sentinel element&lt;/li&gt;
&lt;li&gt;loads the next page when the sentinel enters the viewport&lt;/li&gt;
&lt;li&gt;appends characters instead of replacing them&lt;/li&gt;
&lt;li&gt;loads the third page on repeated intersections&lt;/li&gt;
&lt;li&gt;shows a loading indicator while fetching the next page&lt;/li&gt;
&lt;li&gt;hides the loading indicator once the next page loads&lt;/li&gt;
&lt;li&gt;shows end of list when there are no more pages&lt;/li&gt;
&lt;li&gt;does not fetch again once the end is reached&lt;/li&gt;
&lt;li&gt;disconnects the observer on unmount&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Infinite scroll is one of those tasks that shows up again and again in frontend interviews and real products.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/infinite-scroll" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Roll dices</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 02 Sep 2026 08:29:15 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-roll-dices-4fad</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-roll-dices-4fad</guid>
      <description>&lt;p&gt;Most of us write &lt;code&gt;Math.floor(Math.random() * n)&lt;/code&gt; on autopilot and only realize later that the boundaries are wrong — inclusive when you wanted exclusive, or off by one. This challenge replaces that guesswork with practice: build a dice roller and three random number generators where getting the range right is the whole point.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Build a dice roller app plus three random number generators, practicing how to convert &lt;code&gt;Math.random()&lt;/code&gt; into random integer values across different ranges.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/roll-dices" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/roll-dices&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A form with an input that defaults to &lt;code&gt;3&lt;/code&gt; and only accepts values between &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;6&lt;/code&gt;, submitted with a &lt;strong&gt;Roll&lt;/strong&gt; button.&lt;/li&gt;
&lt;li&gt;On submit, roll as many dice as the input value — rendering one &lt;code&gt;Dice&lt;/code&gt; component per dice, each showing a random value between &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;6&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add three random number generators, each with its own &lt;strong&gt;Roll&lt;/strong&gt; button and a result display, producing random integers:

&lt;ul&gt;
&lt;li&gt;Between &lt;code&gt;-10&lt;/code&gt; and &lt;code&gt;10&lt;/code&gt;, both included.&lt;/li&gt;
&lt;li&gt;Between &lt;code&gt;7&lt;/code&gt; and &lt;code&gt;14&lt;/code&gt;, both &lt;strong&gt;not&lt;/strong&gt; included.&lt;/li&gt;
&lt;li&gt;Between &lt;code&gt;0&lt;/code&gt; and &lt;code&gt;255&lt;/code&gt;, both included.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;Dice.tsx&lt;/code&gt; component is provided and read-only, so you can focus on state and logic instead of markup.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Default input value is 3&lt;/li&gt;
&lt;li&gt;Does not roll more than 6 dice&lt;/li&gt;
&lt;li&gt;Does not roll fewer than 1 dice&lt;/li&gt;
&lt;li&gt;Clicking roll renders a number of dice equal to the input value&lt;/li&gt;
&lt;li&gt;Random values map to valid dice faces&lt;/li&gt;
&lt;li&gt;First random generator returns values between -10 and 10, both included&lt;/li&gt;
&lt;li&gt;Second random generator returns values between 8 and 13, both not included&lt;/li&gt;
&lt;li&gt;Third random generator returns values between 0 and 255, both included&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;If you have ever doubted whether your random range formula is right, this is a quick, test-driven way to lock it in. You'll finish confident mapping &lt;code&gt;Math.random()&lt;/code&gt; to any range — and rendering a list of components from state while you are at it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/roll-dices" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Calendar Events</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 26 Aug 2026 11:27:51 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-calendar-events-4k87</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-calendar-events-4k87</guid>
      <description>&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Build a calendar that renders events on their days, supports selecting a day, and lets you add and delete events — practicing state management and data transformation keyed by absolute date strings.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/calendar-events" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/calendar-events&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Select a day by clicking it, highlighting the selected cell.&lt;/li&gt;
&lt;li&gt;Show the events of the selected day in a panel below the calendar, including a heading with the selected date.&lt;/li&gt;
&lt;li&gt;Add a new event via a text input and an "Add" button; empty or whitespace-only titles are ignored.&lt;/li&gt;
&lt;li&gt;Delete an event from the selected day via its delete button.&lt;/li&gt;
&lt;li&gt;Show a "no events" message for a selected day without events.&lt;/li&gt;
&lt;li&gt;Keep events intact when navigating between months — events are keyed by absolute &lt;code&gt;YYYY-MM-DD&lt;/code&gt; dates.&lt;/li&gt;
&lt;li&gt;Show an event dot on every day that has at least one event.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Components and the month-grid logic are already wired — your job is the events state: events, the selected day, filtering, and add/delete.&lt;/li&gt;
&lt;li&gt;Pass your events to &lt;code&gt;buildMonthDays(date, events)&lt;/code&gt; and the dots appear automatically.&lt;/li&gt;
&lt;li&gt;Filter events per day by comparing each event's date to the selected day; this keeps events stable across month navigation.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Does not show dots on a day without events&lt;/li&gt;
&lt;li&gt;Selecting a day highlights it&lt;/li&gt;
&lt;li&gt;Shows the selected date in the panel heading&lt;/li&gt;
&lt;li&gt;Adds a new event via the Add button&lt;/li&gt;
&lt;li&gt;Adds a new event when pressing Enter&lt;/li&gt;
&lt;li&gt;Ignores empty titles when adding&lt;/li&gt;
&lt;li&gt;Shows a dot on the day of a newly added event&lt;/li&gt;
&lt;li&gt;Supports multiple events on the same day&lt;/li&gt;
&lt;li&gt;Shows only the events of the selected day&lt;/li&gt;
&lt;li&gt;Deletes an event from the selected day&lt;/li&gt;
&lt;li&gt;Keeps events when navigating between months&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Whether you're prepping for interviews or sharpening your state skills, this is a compact, satisfying build — the calendar is already done, so you can focus entirely on managing events like a pro.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/calendar-events" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Calendar</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Thu, 20 Aug 2026 17:00:37 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-calendar-3ak6</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-calendar-3ak6</guid>
      <description>&lt;p&gt;We all reach for a date library the moment a calendar shows up in a feature request. But underneath every grid is plain JavaScript — counting days, offsetting weekdays, and rolling years over. This challenge drops the library and puts you in charge.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;The calendar components are already provided, so your job is the logic: render the correct days, highlight today, navigate between months, and handle leap years with plain JavaScript date math.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/calendar" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/calendar&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;p&gt;• Render the app title "Calendar" and the weekday header (Mon through Sun).&lt;br&gt;
• Show the current month and year in the header (e.g. August 2026).&lt;br&gt;
• Render the correct number of days for the selected month (28, 29, 30, or 31).&lt;br&gt;
• Place the 1st day of the month in the correct weekday column.&lt;br&gt;
• Fill empty cells with days from the previous and next month so the grid always completes full weeks, dimming those days visually.&lt;br&gt;
• Navigate to the previous and next month.&lt;br&gt;
• Highlight the current day (today) in the grid.&lt;br&gt;
• Change the year correctly when navigating past December or before January.&lt;br&gt;
• Handle leap years correctly (February has 29 days in a leap year, 28 otherwise).&lt;/p&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;p&gt;• &lt;code&gt;new Date(year, month + 1, 0).getDate()&lt;/code&gt; returns the number of days in a month — leap years included.&lt;br&gt;
• The week starts on Monday, so the leading offset for the 1st day is &lt;code&gt;(getDay() + 6) % 7&lt;/code&gt;.&lt;br&gt;
• &lt;code&gt;new Date(year, month + offset, 1)&lt;/code&gt; rolls the year over automatically when navigating past December or January.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;renders the app title&lt;/li&gt;
&lt;li&gt;renders the seven weekday labels&lt;/li&gt;
&lt;li&gt;shows the current month and year in the header&lt;/li&gt;
&lt;li&gt;renders the correct number of days for the current month&lt;/li&gt;
&lt;li&gt;places the 1st day on the correct weekday&lt;/li&gt;
&lt;li&gt;fills the grid with days from the previous and next month&lt;/li&gt;
&lt;li&gt;navigates to the next month&lt;/li&gt;
&lt;li&gt;navigates to the previous month&lt;/li&gt;
&lt;li&gt;changes the year when navigating past December&lt;/li&gt;
&lt;li&gt;changes the year when navigating before January&lt;/li&gt;
&lt;li&gt;highlights today's date&lt;/li&gt;
&lt;li&gt;does not highlight any day when viewing another month&lt;/li&gt;
&lt;li&gt;renders 28 days for February in a non-leap year&lt;/li&gt;
&lt;li&gt;renders 29 days for February in a leap year&lt;/li&gt;
&lt;li&gt;renders 30 days for a 30-day month&lt;/li&gt;
&lt;li&gt;uses five weeks when the month fits in five&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;You'll walk away confident counting days, offsetting weekdays, and handling leap years without a single dependency. 16 tests will tell you exactly where your grid breaks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/calendar" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>🚀 New React Challenge: GitHub Contribution Heatmap</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 05 Aug 2026 08:24:32 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-github-contribution-heatmap-3im1</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-github-contribution-heatmap-3im1</guid>
      <description>&lt;p&gt;Fetching data in React without a library means juggling useEffect, abort controllers, isLoading booleans, error state, and cache invalidation — all by hand. SWR, TanStack Query, and RTK Query solve all of that out of the box. This challenge has the grid and components pre-built — your job is to wire up SWR and bring the GitHub-style heatmap to life.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Fetch contribution data for a GitHub-style heatmap using SWR. The grid and components are already built — you wire up data fetching with loading skeletons, error handling, and year navigation to make it work.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/github-contribution-heatmap" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/github-contribution-heatmap&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Fetch contribution data from &lt;code&gt;https://example-heatmap?year={year}&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Write a custom fetcher that checks &lt;code&gt;res.ok&lt;/code&gt;, parses the error body, and throws on failure — SWR won't know a request failed unless the fetcher throws&lt;/li&gt;
&lt;li&gt;Display a loading skeleton while data is being fetched&lt;/li&gt;
&lt;li&gt;Display an error skeleton with the server's error message when the request fails&lt;/li&gt;
&lt;li&gt;Display the heatmap grid with flattened contributions on success&lt;/li&gt;
&lt;li&gt;Allow switching between years (2023–2026) with interactive buttons&lt;/li&gt;
&lt;li&gt;Highlight the currently selected year button&lt;/li&gt;
&lt;li&gt;Calculate the offset so January 1st aligns with the correct weekday column&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;contributions&lt;/code&gt; is a 2D array (weeks × days) — flatten it with &lt;code&gt;.flat()&lt;/code&gt; before passing to &lt;code&gt;HeatmapGrid&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The mock API has a random 300-500ms delay and fails ~20% of the time&lt;/li&gt;
&lt;li&gt;The custom fetcher pattern is universal: SWR, TanStack Query, and RTK Query all require you to throw on non-ok responses&lt;/li&gt;
&lt;li&gt;The data is from Linus Torvalds' real GitHub contributions — every cell reflects actual commits, merges, and pull requests&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Renders the app title&lt;/li&gt;
&lt;li&gt;Shows skeleton while loading&lt;/li&gt;
&lt;li&gt;Displays heatmap grid with contributions when data loads&lt;/li&gt;
&lt;li&gt;Shows skeleton with error when request fails&lt;/li&gt;
&lt;li&gt;Highlights 2026 as the selected year button&lt;/li&gt;
&lt;li&gt;Fetches new data when switching to a different year&lt;/li&gt;
&lt;li&gt;Aligns January 1st to the correct weekday for each year&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Whether you're new to SWR or already using TanStack Query, this challenge reinforces the fetch-then-render pattern that every production React app relies on. Plus, you get to see Linus Torvalds' actual commit history rendered as a heatmap — pretty cool.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/github-contribution-heatmap" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>Typing Polymorphic React Components in TypeScript</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 29 Jul 2026 13:33:00 +0000</pubDate>
      <link>https://dev.to/reactchallenges/typing-polymorphic-react-components-in-typescript-cl6</link>
      <guid>https://dev.to/reactchallenges/typing-polymorphic-react-components-in-typescript-cl6</guid>
      <description>&lt;p&gt;I recently came across an interview question about advanced TypeScript patterns, specifically how to type a &lt;code&gt;Button&lt;/code&gt; component that can also render as a link. These are the kinds of concepts that are easy to forget, especially if you don't write as much code by hand anymore because AI handles a lot of it.&lt;/p&gt;

&lt;p&gt;That's why it's worth revisiting them from time to time. One of the best ways to check whether you truly understand a concept is to explain it to yourself and honestly ask whether someone else could understand that explanation. So here we are.&lt;/p&gt;

&lt;h2&gt;
  
  
  Everything optional
&lt;/h2&gt;

&lt;p&gt;Everything is optional, so TypeScript can't infer whether this component should behave as a button or a link. Since there is no relationship between the props, invalid combinations are allowed.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;href&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;target&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;type&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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="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;props&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;if &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;href&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;a&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;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="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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ✅ No TypeScript error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Union types
&lt;/h2&gt;

&lt;p&gt;TypeScript says:&lt;/p&gt;

&lt;p&gt;"I have a value whose type is &lt;code&gt;LinkProps | ButtonProps&lt;/code&gt;. I'll check whether it matches one of the union members."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LinkProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;href&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;target&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;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="p"&gt;};&lt;/span&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="kd"&gt;type&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LinkProps&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&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;props&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;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&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;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;a&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;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="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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Property 'disabled' does not exist on type 'LinkProps'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Discriminated unions
&lt;/h2&gt;

&lt;p&gt;Sometimes you don't want to infer the rendered element from the props. Instead, you want the user to choose it explicitly.&lt;/p&gt;

&lt;p&gt;TypeScript says:&lt;/p&gt;

&lt;p&gt;"I have a value whose type is &lt;code&gt;LinkProps | ButtonProps&lt;/code&gt;. I'll use the &lt;code&gt;as&lt;/code&gt; property to determine which one it is."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;LinkProps&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;href&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;target&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;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="p"&gt;};&lt;/span&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;as&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;type&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;submit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;reset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;disabled&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="nx"&gt;boolean&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="p"&gt;};&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LinkProps&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nx"&gt;ButtonProps&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;props&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;if &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="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;a&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;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;a&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;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="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;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;;&lt;/span&gt; &lt;span class="c1"&gt;// ❌ Property 'href' does not exist on type 'ButtonProps'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Generic polymorphic components
&lt;/h2&gt;

&lt;p&gt;In React 19+, the recommended utility type is &lt;code&gt;React.ComponentProps&amp;lt;T&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It gives you all the props supported by the element or component represented by &lt;code&gt;T&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&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;ElementType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;as&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="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&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;ComponentProps&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Button&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt; &lt;span class="kd"&gt;extends&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;ElementType&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;Props&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;T&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="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="k"&gt;as&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="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&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;Component&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;button&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Component&lt;/span&gt; &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;rest&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;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; In production code you'll often see &lt;code&gt;Omit&amp;lt;React.ComponentProps&amp;lt;T&amp;gt;, "as"&amp;gt;&lt;/code&gt; instead of &lt;code&gt;React.ComponentProps&amp;lt;T&amp;gt;&lt;/code&gt;. This removes any existing &lt;code&gt;as&lt;/code&gt; prop from the rendered component. Since HTML elements like &lt;code&gt;"button"&lt;/code&gt; and &lt;code&gt;"a"&lt;/code&gt; don't define an &lt;code&gt;as&lt;/code&gt; prop, the simplified version used here is sufficient.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now TypeScript automatically infers the correct props based on the value of &lt;code&gt;as&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c1"&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;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c1"&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;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"button"&lt;/span&gt; &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c1"&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;as&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"a"&lt;/span&gt; &lt;span class="na"&gt;disabled&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;// ❌&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; If you're using React 18 or earlier, use &lt;code&gt;React.ComponentPropsWithoutRef&amp;lt;T&amp;gt;&lt;/code&gt; instead. Before React 19, &lt;code&gt;ref&lt;/code&gt; wasn't treated as a normal prop for function components, so excluding it was usually the correct choice.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;React.ComponentProps&amp;lt;T&amp;gt;&lt;/code&gt; is equivalent to saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Give me all the props that the element or component &lt;code&gt;T&lt;/code&gt; accepts."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Unlike union types, there's no need to manually define every possible combination (&lt;code&gt;LinkProps | ButtonProps | ...&lt;/code&gt;). The props are computed directly from the generic type &lt;code&gt;T&lt;/code&gt;, making the component scalable to any HTML element or custom React component.&lt;/p&gt;

</description>
      <category>react</category>
      <category>typescript</category>
      <category>javascript</category>
      <category>frontend</category>
    </item>
    <item>
      <title>🚀 New React Challenge: useEffect vs useLayoutEffect</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Wed, 22 Jul 2026 16:16:37 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-useeffect-vs-uselayouteffect-1e0g</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-useeffect-vs-uselayouteffect-1e0g</guid>
      <description>&lt;p&gt;You've used useEffect a thousand times. But did you know it runs &lt;em&gt;after&lt;/em&gt; the browser paints? That means if you're measuring the DOM to position an element, users will see a flicker — the element renders at the wrong position, then snaps into place. useLayoutEffect fixes that by running &lt;em&gt;before&lt;/em&gt; paint. This challenge proves it with a tooltip.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;A tooltip component needs to center itself by measuring its own width. The starter uses useEffect, causing a visible flicker — the tooltip appears uncentered for a moment before snapping to the middle. Replace it with useLayoutEffect and the measurement happens before the browser paints, giving you a perfect first frame.&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/use-effect-vs-use-layout-effect" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/use-effect-vs-use-layout-effect&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Replace &lt;code&gt;useEffect&lt;/code&gt; with &lt;code&gt;useLayoutEffect&lt;/code&gt; in the TooltipContent component so the tooltip is centered before the browser paints, avoiding the flicker.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;useLayoutEffect&lt;/code&gt; runs before paint — use it for DOM measurements.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useEffect&lt;/code&gt; runs after paint — use it for logging, subscriptions, and side effects that don't affect layout.&lt;/li&gt;
&lt;li&gt;Pro tip: if the flicker is too fast to see, enable CPU throttling (4x or 6x) in DevTools → Performance tab.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Uses useLayoutEffect for the DOM measurement&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;This is one of those hooks that doesn't come up often — but when it does, knowing the difference between useEffect and useLayoutEffect is the difference between a polished UI and a janky one. A single line change, a world of difference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/use-effect-vs-use-layout-effect" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Invoker modal</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Tue, 14 Jul 2026 16:40:48 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-invoker-modal-3000</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-invoker-modal-3000</guid>
      <description>&lt;p&gt;Tired of writing &lt;code&gt;useState(false)&lt;/code&gt; and &lt;code&gt;onClick&lt;/code&gt; handlers every time you need a modal? The browser already has a declarative API for that.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Learn how to open and close a &lt;code&gt;&amp;lt;dialog&amp;gt;&lt;/code&gt; using only HTML attributes — no React state, no &lt;code&gt;useState&lt;/code&gt;, no event handlers at all. The Invoker Commands API lets buttons control dialogs natively.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 &lt;a href="https://www.reactchallenges.com/challenges/invoker-modal" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/invoker-modal&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Wire the "Contact Us" button to open the dialog using &lt;code&gt;command&lt;/code&gt; and &lt;code&gt;commandfor&lt;/code&gt; attributes&lt;/li&gt;
&lt;li&gt;Wire the "Close" button to close the dialog&lt;/li&gt;
&lt;li&gt;The dialog must start closed&lt;/li&gt;
&lt;li&gt;Keep the existing form fields and &lt;code&gt;data-testid&lt;/code&gt; attributes intact&lt;/li&gt;
&lt;li&gt;Do not remove the TypeScript module augmentation block&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💡 Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;A button uses &lt;code&gt;command&lt;/code&gt; and &lt;code&gt;commandfor&lt;/code&gt; to tell the browser to call &lt;code&gt;showModal()&lt;/code&gt; or &lt;code&gt;close()&lt;/code&gt; — no JavaScript needed.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;useId()&lt;/code&gt; from React is the idiomatic way to generate a unique id for linking button to dialog.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;declare module "react"&lt;/code&gt; block already adds &lt;code&gt;command&lt;/code&gt; and &lt;code&gt;commandfor&lt;/code&gt; to React's button types.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🧪 Tests
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Renders the app title&lt;/li&gt;
&lt;li&gt;Renders the open button with command attributes&lt;/li&gt;
&lt;li&gt;Matches the button commandfor with the dialog id&lt;/li&gt;
&lt;li&gt;Dialog does not have the open attribute initially&lt;/li&gt;
&lt;li&gt;Close button has command close with matching commandfor&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This challenge is perfect for developers who want to rely more on the platform and write less JavaScript. You'll learn a native browser API that makes modals simpler, more accessible, and more resilient.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/invoker-modal" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontendchallenge</category>
      <category>frontend</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Tier List</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Mon, 06 Jul 2026 11:44:05 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-tier-list-3n4g</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-tier-list-3n4g</guid>
      <description>&lt;p&gt;Ever built a drag-and-drop UI with just the native browser API? No &lt;code&gt;react-beautiful-dnd&lt;/code&gt;, no &lt;code&gt;dnd-kit&lt;/code&gt; — just &lt;code&gt;dragStart&lt;/code&gt;, &lt;code&gt;dragOver&lt;/code&gt;, and &lt;code&gt;drop&lt;/code&gt; events. In this challenge, you'll build a Tier List app where users upload images and rank them A through F by dragging, mastering the HTML5 Drag and Drop API along the way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/tier-list" rel="noopener noreferrer"&gt;https://www.reactchallenges.com/challenges/tier-list&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🧩 Overview
&lt;/h2&gt;

&lt;p&gt;Build a tier maker app where users upload images and drag them into ranked tiers (A through F) — practicing HTML5 Drag and Drop and file uploads in React.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✅ Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Render a "Tier List" title at the top of the page&lt;/li&gt;
&lt;li&gt;Render six tier rows labeled A, B, C, D, E, F with the correct background colors&lt;/li&gt;
&lt;li&gt;Include two action buttons: Add (file picker) and Reset (moves all images back)&lt;/li&gt;
&lt;li&gt;Provide a selector area at the bottom where unassigned images appear&lt;/li&gt;
&lt;li&gt;Start with an empty selector and empty tier rows&lt;/li&gt;
&lt;li&gt;File upload: selecting images via file picker adds them to the selector; dragging files from desktop onto the selector also works&lt;/li&gt;
&lt;li&gt;Drag and drop: drag images from selector to tiers, between tiers, and back to the selector&lt;/li&gt;
&lt;li&gt;Highlight the drop zone while dragging over it&lt;/li&gt;
&lt;li&gt;Reset moves all images from tier rows back into the selector area&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you've never worked with the native Drag and Drop API before, this is the perfect challenge to get comfortable with it. You'll walk away knowing how to handle file uploads, drag events, and complex UI state — all inside a custom hook.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/tier-list" rel="noopener noreferrer"&gt;🔥 Start the Challenge Now&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
  </channel>
</rss>
