<?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>🚀 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>
    <item>
      <title>Cognitive Surrender and Why You Should Still Write Code by Hand</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Mon, 22 Jun 2026 08:47:32 +0000</pubDate>
      <link>https://dev.to/reactchallenges/cognitive-surrender-and-why-you-should-still-write-code-by-hand-29ab</link>
      <guid>https://dev.to/reactchallenges/cognitive-surrender-and-why-you-should-still-write-code-by-hand-29ab</guid>
      <description>&lt;p&gt;A study from the University of Pennsylvania introduced a term that should make every developer pause: &lt;strong&gt;cognitive surrender&lt;/strong&gt;. Across 9,500 trials with over 1,300 participants, researchers found that when an AI provided an answer — even a wrong one — people accepted it without scrutiny 73.2% of the time. Not because the answers were convincing. Because the mere presence of a confident AI response was enough to shut down the part of the brain that says &lt;em&gt;"wait, let me think about this."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you write code for a living, you already know where this is going.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Try it in practice: &lt;a href="https://www.reactchallenges.com/challenges/055-simple-pagination" rel="noopener noreferrer"&gt;Simple pagination&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The shortcut that becomes the habit
&lt;/h2&gt;

&lt;p&gt;The researchers describe a shift from two systems of thinking to a third: &lt;strong&gt;artificial cognition&lt;/strong&gt;. Instead of reasoning through a problem, you ask the machine. Instead of verifying, you paste and move on.&lt;/p&gt;

&lt;p&gt;For developers, this is now routine. You need a pagination component. You type a prompt. You get a &lt;code&gt;fetch&lt;/code&gt; inside a &lt;code&gt;useEffect&lt;/code&gt;, some &lt;code&gt;useState&lt;/code&gt;, a loading skeleton. It works. You ship it. You don't think about it again.&lt;/p&gt;

&lt;p&gt;But the study found something revealing: participants with higher &lt;strong&gt;fluid IQ&lt;/strong&gt; — the ability to solve novel problems — were far less likely to be misled by faulty AI. The skill that protected them wasn't knowing more. It was &lt;strong&gt;the habit of reasoning things through&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where AI belongs (and where it doesn't)
&lt;/h2&gt;

&lt;p&gt;None of this means you should ditch AI. It means you should be intentional about where you deploy it.&lt;/p&gt;

&lt;p&gt;AI is great for &lt;strong&gt;mechanical, repetitive work that requires zero reasoning&lt;/strong&gt;. Generating Storybook stories for every component variant. Writing boilerplate unit tests that follow a predictable pattern. Scaffolding a folder structure. Tasks where the thinking is already done and what's left is typing.&lt;/p&gt;

&lt;p&gt;But when the task involves a decision — &lt;em&gt;how should this state be structured? what does the user need when this errors? should this be optimistic or not?&lt;/em&gt; — that's where you want the friction. That's the muscle you don't want to atrophy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use it or lose it
&lt;/h2&gt;

&lt;p&gt;Writing a pagination component is not hard. Fetch data, track the page, handle loading, surface errors. An LLM can do it in three seconds.&lt;/p&gt;

&lt;p&gt;But the point of writing it yourself is not the result. It's the friction.&lt;/p&gt;

&lt;p&gt;When you write a &lt;code&gt;fetch&lt;/code&gt; call manually, you remember how &lt;code&gt;AbortController&lt;/code&gt; works. When you toggle loading and error states by hand, you internalize async UI patterns. When you decide what the retry button looks like, you think about the user. None of that happens when you accept a generated block and move on.&lt;/p&gt;

&lt;p&gt;The experiment design was telling: participants used a modified LLM that gave wrong answers half the time. When the AI was accurate, 93% accepted it. When it was faulty, that only dropped to 80%. Even when the machine was &lt;strong&gt;demonstrably wrong&lt;/strong&gt;, four out of five went along with it. The AI didn't just provide answers — it &lt;strong&gt;lowered the threshold for scrutiny&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is not about rejecting AI tools. It's about recognizing that reasoning ability — like any other skill — &lt;strong&gt;atrophies without use&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep the muscle alive
&lt;/h2&gt;

&lt;p&gt;The fix is mechanically simple: &lt;strong&gt;practice without the net&lt;/strong&gt;. Not every day, not for every task. But regularly enough that the mental pathways stay warm.&lt;/p&gt;

&lt;p&gt;Pick a problem you could solve with a prompt and solve it manually. Write the pagination from an empty file. Handle the errors. Wire up the loading states. The value is not the code — it's staying fluent enough to know when the AI is wrong, and sharp enough to fix it without asking the AI again.&lt;/p&gt;

&lt;p&gt;Delegate the boilerplate. Protect the thinking.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Try it in practice: &lt;a href="https://www.reactchallenges.com/challenges/055-simple-pagination" rel="noopener noreferrer"&gt;Simple pagination&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>productivity</category>
      <category>development</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Simple Pagination</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Sun, 21 Jun 2026 10:35:57 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-simple-pagination-5am4</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-simple-pagination-5am4</guid>
      <description>&lt;p&gt;In a time where AI writes most of our boilerplate, manually wiring a fetch with loading, error, and pagination states is exactly the kind of thing that slips through the cracks — and exactly what keeps coming up in job interviews.&lt;/p&gt;




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

&lt;p&gt;A plain fetch with pagination and manual loading and error handling. No libraries, no abstractions — just &lt;code&gt;useState&lt;/code&gt;, &lt;code&gt;useEffect&lt;/code&gt;, and a mock API that delays, paginates, and randomly fails. The kind of challenge that keeps your fundamentals sharp.&lt;/p&gt;

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




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

&lt;ul&gt;
&lt;li&gt;Fetch users from &lt;code&gt;https://example/users?page={page}&lt;/code&gt; and display them in a table (ID, Name, Last name). The API returns up to 10 users per page.&lt;/li&gt;
&lt;li&gt;Show a loading skeleton while fetching.&lt;/li&gt;
&lt;li&gt;Display page info: &lt;code&gt;Page {page} of {totalPages} ({count} users)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Pagination buttons:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;First&lt;/strong&gt;: goes to page 0. Disabled when on page 0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Previous&lt;/strong&gt;: goes to the previous page. Disabled when on page 0.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Next&lt;/strong&gt;: goes to the next page. Disabled when on the last page.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Last&lt;/strong&gt;: goes to the last page. Disabled when on the last page.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;All buttons disabled when count is 0 or while loading.&lt;/li&gt;
&lt;li&gt;Display an error message when the request fails.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you've been leaning on AI for the boilerplate lately, this one will remind you how much muscle memory matters. Simple fetch, clean state, solid edge cases — exactly what separates a working prototype from interview-ready code.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/simple-pagination" 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>
    <item>
      <title>🚀 New React Challenge: Build a Spreadsheet with Formula Evaluation</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Thu, 11 Jun 2026 09:55:42 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-react-challenge-build-a-spreadsheet-with-formula-evaluation-3hic</link>
      <guid>https://dev.to/reactchallenges/new-react-challenge-build-a-spreadsheet-with-formula-evaluation-3hic</guid>
      <description>&lt;p&gt;You've built todo apps, counters, and forms. But can you handle a grid of 50 cells that reference each other through formulas? This challenge pushes your state management skills into real spreadsheet territory — formula evaluation, two-way cell bindings, and an interface that juggles editing, selection, and keyboard shortcuts all at once.&lt;/p&gt;

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




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

&lt;p&gt;Build a spreadsheet with real-time formula evaluation. You'll wire up a 10-row × 5-column grid where cells support basic values and Excel-style formulas (like =A1+B2), column and row selection, and a formula bar that mirrors what you're typing.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;Render a spreadsheet with column headers A through E and rows 1 through 10&lt;/li&gt;
&lt;li&gt;Each cell uses an &lt;code&gt;&amp;lt;output&amp;gt;&lt;/code&gt; element for the computed value and an &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; overlaid for editing&lt;/li&gt;
&lt;li&gt;Click a cell to edit; press Enter or blur to commit the change&lt;/li&gt;
&lt;li&gt;Formulas starting with &lt;code&gt;=&lt;/code&gt; must be evaluated:

&lt;ul&gt;
&lt;li&gt;Arithmetic: &lt;code&gt;=1+1&lt;/code&gt; → &lt;code&gt;2&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Cell references: A1=&lt;code&gt;5&lt;/code&gt; and B1=&lt;code&gt;=A1+3&lt;/code&gt; → &lt;code&gt;8&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Click a column header to select/deselect that column&lt;/li&gt;
&lt;li&gt;Click a row number to select/deselect that row&lt;/li&gt;
&lt;li&gt;Selecting a column deselects any row and vice-versa&lt;/li&gt;
&lt;li&gt;Backspace clears the selected column or row&lt;/li&gt;
&lt;li&gt;Click outside the table deselects everything&lt;/li&gt;
&lt;li&gt;A formula bar (&lt;code&gt;fx&lt;/code&gt;) mirrors the editing cell's value&lt;/li&gt;
&lt;li&gt;Cells must start empty — no default values&lt;/li&gt;
&lt;/ul&gt;




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

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;useState&lt;/code&gt; for cells, selected column, and selected row. No need for useReducer here.&lt;/li&gt;
&lt;li&gt;Each cell uses two overlapping layers: a visible &lt;code&gt;&amp;lt;output&amp;gt;&lt;/code&gt; for the computed value and an invisible &lt;code&gt;&amp;lt;input&amp;gt;&lt;/code&gt; for the raw formula. Toggle with &lt;code&gt;opacity-0&lt;/code&gt; / &lt;code&gt;opacity-100&lt;/code&gt; so the input stays mounted.&lt;/li&gt;
&lt;li&gt;Evaluate formulas with &lt;code&gt;eval&lt;/code&gt;: generate JS &lt;code&gt;const&lt;/code&gt; declarations from all cell values, wrap them in an IIFE, and evaluate. Recompute &lt;strong&gt;every&lt;/strong&gt; cell on any change — cells can reference each other.&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 spreadsheet with column headers A-E and rows 1-10&lt;/li&gt;
&lt;li&gt;renders cells with initial empty values&lt;/li&gt;
&lt;li&gt;allows editing a cell and displays the new computed value&lt;/li&gt;
&lt;li&gt;evaluates a simple formula&lt;/li&gt;
&lt;li&gt;evaluates a formula with cell references&lt;/li&gt;
&lt;li&gt;re-evaluates formulas when a referenced cell is cleared&lt;/li&gt;
&lt;li&gt;selects a column when clicking the column header&lt;/li&gt;
&lt;li&gt;deselects column when clicking the same header again&lt;/li&gt;
&lt;li&gt;selects a row when clicking the row number&lt;/li&gt;
&lt;li&gt;deselects row when clicking the same row number again&lt;/li&gt;
&lt;li&gt;deselects column when selecting a row and vice-versa&lt;/li&gt;
&lt;li&gt;clears the column when Backspace is pressed with a column selected&lt;/li&gt;
&lt;li&gt;clears the row when Backspace is pressed with a row selected&lt;/li&gt;
&lt;li&gt;deselects column when clicking outside the spreadsheet&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;This one will stretch your understanding of React state in ways a simple counter or todo list never could. Formula engines, overlay editing, and cascading recomputation — all with just hooks and vanilla React.&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>frontend</category>
      <category>frontendchallenge</category>
    </item>
    <item>
      <title>Your tests pass. Your linter doesn't.</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Mon, 08 Jun 2026 13:02:34 +0000</pubDate>
      <link>https://dev.to/reactchallenges/your-tests-pass-your-linter-doesnt-4mga</link>
      <guid>https://dev.to/reactchallenges/your-tests-pass-your-linter-doesnt-4mga</guid>
      <description>&lt;p&gt;Every React developer has written code like this:&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;function&lt;/span&gt; &lt;span class="nf"&gt;TodoList&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;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setList&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="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;showClearCompleted&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setShowClearCompleted&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="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;setShowClearCompleted&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;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&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;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isComplete&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;list&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The app works. The tests pass. The feature is shipped. And nobody notices that this code has a bug — not a functional bug, but a &lt;strong&gt;structural one&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The silent lie of derived state
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;setShowClearCompleted&lt;/code&gt; inside a &lt;code&gt;useEffect&lt;/code&gt; that watches &lt;code&gt;list&lt;/code&gt; is the React equivalent of buying a notebook, writing down the result of &lt;code&gt;2 + 2&lt;/code&gt;, and then, every time one of the numbers changes, erasing it and writing &lt;code&gt;4&lt;/code&gt; again — instead of just asking "what is &lt;code&gt;2 + 2&lt;/code&gt;?" when you need the answer.&lt;/p&gt;

&lt;p&gt;The value of &lt;code&gt;showClearCompleted&lt;/code&gt; is &lt;strong&gt;derived&lt;/strong&gt; from &lt;code&gt;list&lt;/code&gt;. It is not a separate piece of state. It is a computation over state you already have. Yet the code above treats it as if it were independent — storing it, syncing it, and triggering an extra render to apply it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Try it yourself: &lt;a href="https://www.reactchallenges.com/challenges/best-practices" rel="noopener noreferrer"&gt;Challenge #53 — Best Practices&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Here is what the corrected version looks like:&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;function&lt;/span&gt; &lt;span class="nf"&gt;TodoList&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;list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setList&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;showClearCompleted&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;some&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;task&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;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isComplete&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No effect. No extra state variable. No cascading render. Just a value computed from state you already own. The component renders, the computation runs, the UI updates — all in a single pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters: cascading renders
&lt;/h2&gt;

&lt;p&gt;When you call &lt;code&gt;setState&lt;/code&gt; inside a &lt;code&gt;useEffect&lt;/code&gt;, React has to do &lt;strong&gt;two renders&lt;/strong&gt; instead of one. The first render computes the effect dependencies. The effect fires. It calls &lt;code&gt;setState&lt;/code&gt;. React schedules a second render with the new state.&lt;/p&gt;

&lt;p&gt;In a small component, you won't feel it. In a page with dozens of components, each with their own derived-state effects, the cascade compounds. You get flickers, stale intermediate states, and a performance profile that is needlessly heavy for no reason at all.&lt;/p&gt;

&lt;p&gt;And the worst part? If you only test the output — the DOM, the rendered text, the visible behavior — &lt;strong&gt;you will never catch this&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Most platforms don't check. We do.
&lt;/h2&gt;

&lt;p&gt;Go to any coding challenge site. Pick a React challenge. Write the version with &lt;code&gt;useEffect&lt;/code&gt;. Run the tests. They pass. Congratulations, you solved it.&lt;/p&gt;

&lt;p&gt;But did you write &lt;em&gt;good React&lt;/em&gt;? The answer depends on what "good" means. If it means "the tests pass," then yes. If it means "idiomatic, performant, maintainable React that your coworkers won't silently judge during code review," then no.&lt;/p&gt;

&lt;p&gt;Challenge #53 on React Challenges is different. When you hit &lt;strong&gt;Run Tests&lt;/strong&gt;, two things happen:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your code runs against a suite of behavioral tests (does the todo list add, delete, toggle, and clear items?)&lt;/li&gt;
&lt;li&gt;Your code is checked against an &lt;strong&gt;ESLint configuration&lt;/strong&gt; that enforces React best practices&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you use &lt;code&gt;useEffect&lt;/code&gt; to sync derived state, the linter catches it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; ✗ App.tsx:29:5  error
   react-hooks/set-state-in-effect
   Calling setState synchronously within an effect causes cascading renders
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the challenge is &lt;strong&gt;not considered complete&lt;/strong&gt; until all lint rules pass.&lt;/p&gt;

&lt;h2&gt;
  
  
  The test-passing trap
&lt;/h2&gt;

&lt;p&gt;There is a quiet assumption in the coding challenge world: if the tests pass, you are done. This assumption trains developers into habits that are fine for a green checkmark and dangerous for a production codebase.&lt;/p&gt;

&lt;p&gt;You can write a component that works and is wrong. You can render the correct UI with code that silently burns through render cycles, hides derived data behind state machines, and uses effects as event handlers because the mental model of React's render cycle never fully clicked.&lt;/p&gt;

&lt;p&gt;Most platforms let you walk away with the green checkmark and a false sense of mastery. We wanted to build one that tells you the second thing: &lt;strong&gt;yes, it works — but it is not right yet&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And for that, you need a linter.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;👉 Try it yourself: &lt;a href="https://www.reactchallenges.com/challenges/best-practices" rel="noopener noreferrer"&gt;Challenge #53 — Best Practices&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>react</category>
      <category>testing</category>
      <category>useeffect</category>
      <category>javascript</category>
    </item>
    <item>
      <title>🚀 New React Challenge: Best Practices</title>
      <dc:creator>ReactChallenges</dc:creator>
      <pubDate>Mon, 08 Jun 2026 11:25:53 +0000</pubDate>
      <link>https://dev.to/reactchallenges/new-challenge-best-practices-280e</link>
      <guid>https://dev.to/reactchallenges/new-challenge-best-practices-280e</guid>
      <description>&lt;p&gt;Your todo list passes all tests. You ship it. But here's the thing no one tells you about interviews — reviewers don't just check that your code works. They look for the 3 anti-patterns hiding in plain sight. This challenge puts ESLint in the reviewer's seat and asks you to clean up the code without breaking a single test.&lt;/p&gt;

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




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

&lt;p&gt;In a real technical interview, solving the logic is only half the battle. Reviewers are trained to spot lazy &lt;code&gt;useState&lt;/code&gt; initializers, derived state hidden inside &lt;code&gt;useEffect&lt;/code&gt;, and impure calls during render. This challenge gives you a working todo list and surfaces exactly those violations through automated linting. Fix all 3 warnings without changing how the app behaves.&lt;/p&gt;




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

&lt;ul&gt;
&lt;li&gt;Fix all ESLint warnings without changing app behavior&lt;/li&gt;
&lt;li&gt;All 6 tests must keep passing after your changes&lt;/li&gt;
&lt;li&gt;Resolve these 3 violations:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;@eslint-react/use-state&lt;/code&gt; — pass a lazy initializer instead of calling the function eagerly&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;react-hooks/set-state-in-effect&lt;/code&gt; — derive &lt;code&gt;showClearCompleted&lt;/code&gt; directly from state, skip the &lt;code&gt;useEffect&lt;/code&gt; workaround&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;@eslint-react/purity&lt;/code&gt; — move &lt;code&gt;new Date()&lt;/code&gt; out of the render path&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;




&lt;p&gt;Three small fixes, three big "aha" moments. Whether you're prepping for React interviews or just want to stop shipping code that silently wastes renders, this one will sharpen the way you read your own components. No new features — just cleaner, faster React.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;a href="https://www.reactchallenges.com/challenges/best-practices" 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>
