{"id":"l-rf-1-3","courseId":"react-fundamentals","lang":"en","kind":"lesson","summary":"Write React components as plain functions, nest them, split them into files with imports and exports, and avoid the naming and nesting mistakes that break them.","html":"<p>Right now <code dir=\"ltr\">App.jsx</code> holds one heading. A real Watchlist screen has a header, a form, a filter bar and a list of movie cards, and some pieces appear many times. If you write it all in one function you get a 300-line component that nobody wants to touch. Components let you name each piece, write it once and reuse it.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">A component is a function</h2>\n<p>Here is a complete component:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">src/App.jsx</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> Header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>My Watchlist&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Movies I want to see&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> App</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">main</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">main</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>Three rules make this work:</p>\n<ol>\n<li><strong>It’s a function that returns JSX.</strong> JSX is the HTML-like syntax inside <code dir=\"ltr\">return</code>. You’ll learn its rules in the next lesson.</li>\n<li><strong>Its name starts with a capital letter.</strong> <code dir=\"ltr\">&lt;Header /&gt;</code> tells React “call the Header function”. A lowercase <code dir=\"ltr\">&lt;header&gt;</code> means the HTML element.</li>\n<li><strong>You use it as a tag, not a function call.</strong> You write <code dir=\"ltr\">&lt;Header /&gt;</code> and React decides when to call <code dir=\"ltr\">Header()</code>. That’s what lets React track it, re-render it and give it state later.</li>\n</ol>\n<p>The parentheses around the multi-line JSX aren’t required by React. They stop JavaScript’s automatic semicolon insertion from ending the <code dir=\"ltr\">return</code> early, which would silently return <code dir=\"ltr\">undefined</code>.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">Components inside components</h2>\n<p>Components nest like HTML. Add a movie card and use it twice:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">src/App.jsx</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Arrival&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>2016&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> App</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">main</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">main</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>You now have two identical cards. That’s obviously not useful yet; the cards need to show different movies. Passing data into a component is what props are for, and they’re coming in Section 2. For now, notice the shape: <code dir=\"ltr\">App</code> is the parent, and <code dir=\"ltr\">Header</code> and the two <code dir=\"ltr\">MovieCard</code>s are its children. Every React app is a tree like this.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">Common mistake</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Defining a component inside another component</span></p>\n<p>It’s tempting to write <code dir=\"ltr\">function Badge() {…}</code> inside <code dir=\"ltr\">MovieCard</code> because only <code dir=\"ltr\">MovieCard</code> uses it. Don’t. Each render of <code dir=\"ltr\">MovieCard</code> creates a new <code dir=\"ltr\">Badge</code> function, React sees a different component type, and it destroys and recreates Badge’s DOM and any state inside it. Always define components at the top level of a file.</p>\n</aside>\n<h2 id=\"sec-3\" tabindex=\"-1\">One component per file</h2>\n<p>When a component is reused or grows past a screenful, give it its own file. The usual layout is a <code dir=\"ltr\">src/components</code> folder:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">src/components/MovieCard.jsx</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Arrival&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">h2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>2016&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">p</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">src/App.jsx</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> Header </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> './components/Header.jsx'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> MovieCard </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">from</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> './components/MovieCard.jsx'</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">;</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> App</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">main</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">main</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>JavaScript modules give you two kinds of export:</p>\n<ul>\n<li><strong>Default export:</strong> <code dir=\"ltr\">export default function MovieCard()</code>. One per file, imported without braces: <code dir=\"ltr\">import MovieCard from '…'</code>.</li>\n<li><strong>Named export:</strong> <code dir=\"ltr\">export function MovieCard()</code>. Any number per file, imported with braces: <code dir=\"ltr\">import { MovieCard } from '…'</code>.</li>\n</ul>\n<p>Both are fine. Many teams prefer named exports because the name is fixed and editors rename it everywhere for you. Pick one convention per project and stick to it. This course uses default exports for components, matching the file Vite generated.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">Tip</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>Name files after components</span></p>\n<p><code dir=\"ltr\">MovieCard.jsx</code> exports <code dir=\"ltr\">MovieCard</code>. When a bug report says “the movie card shows the wrong year”, you know which file to open without searching.</p>\n</aside>\n<h2 id=\"sec-4\" tabindex=\"-1\">Components should be predictable</h2>\n<p>React may call your component function many times: on every update, twice in StrictMode, and sometimes when it’s preparing a screen in the background. So a component should behave like a formula. Given the same inputs, it returns the same JSX and doesn’t change anything outside itself while rendering. Don’t modify global variables, fetch data or touch the DOM directly in the function body. You’ll learn where that kind of work belongs (event handlers and effects) in Section 3.</p>\n<p>Here’s the difference in practice. A component that does <code dir=\"ltr\">visits += 1</code> on a module-level variable will report different numbers in development and production, because StrictMode calls it twice. A component that only reads its inputs and returns JSX gives the same answer no matter how often React calls it.</p>\n<h2 id=\"sec-5\" tabindex=\"-1\">Return a single root</h2>\n<p>A component returns one JSX element. To return siblings without adding an extra <code dir=\"ltr\">&lt;div&gt;</code>, wrap them in a <strong>fragment</strong>:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> App</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Header</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">      &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">MovieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> /></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    &#x3C;/></span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  );</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n<p>A fragment groups elements in your code but adds nothing to the DOM. Use a real element like <code dir=\"ltr\">&lt;main&gt;</code> or <code dir=\"ltr\">&lt;section&gt;</code> when it has meaning for the page’s structure, and a fragment when it doesn’t.</p>\n<p>You can now split a screen into named pieces. Next you’ll learn the rules of JSX itself: why it’s <code dir=\"ltr\">className</code> and not <code dir=\"ltr\">class</code>, how curly braces work, and what JSX turns into when Vite compiles it.</p>\n","toc":[{"id":"sec-1","text":"A component is a function","level":2},{"id":"sec-2","text":"Components inside components","level":2},{"id":"sec-3","text":"One component per file","level":2},{"id":"sec-4","text":"Components should be predictable","level":2},{"id":"sec-5","text":"Return a single root","level":2}],"takeaways":["A component is a JavaScript function whose name starts with a capital letter and that returns JSX.","You use a component like an HTML tag, <code dir=\"ltr\">&lt;MovieCard /&gt;</code>, and React calls the function for you.","Give each reusable component its own file and export it; import it wherever it’s used.","Define components at the top level of a module, never inside another component."],"further":[{"title":"Your First Component","url":"https://react.dev/learn/your-first-component"},{"title":"Importing and Exporting Components","url":"https://react.dev/learn/importing-and-exporting-components"}],"quiz":[{"q":"<p>You write this component and use it as <code dir=\"ltr\">&lt;movieCard /&gt;</code>. Nothing appears, and the console warns about an unrecognized tag. Why?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> movieCard</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>Arrival&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"Components must be written as arrow functions, not with the <code dir=\"ltr\">function</code> keyword.","why":"Both function declarations and arrow functions work as components. The keyword isn’t the problem."},{"text":"The component forgot to call <code dir=\"ltr\">createRoot</code>.","why":"You call <code dir=\"ltr\">createRoot</code> once in main.jsx for the whole app, not inside each component."},{"text":"Lowercase JSX tags are treated as HTML elements, so React tried to create a <code dir=\"ltr\">&lt;moviecard&gt;</code> DOM element.","why":"Correct. React only calls your function when the tag starts with a capital letter. Rename it <code dir=\"ltr\">MovieCard</code>."},{"text":"An <code dir=\"ltr\">&lt;article&gt;</code> can’t be the top element a component returns.","why":"Any single element, including <code dir=\"ltr\">&lt;article&gt;</code>, can be the root of a component’s JSX."}],"answer":2},{"q":"<p>Which line correctly imports a component that <code dir=\"ltr\">src/components/MovieCard.jsx</code> exports with <code dir=\"ltr\">export default function MovieCard()</code>?</p>","options":[{"text":"<code dir=\"ltr\">import MovieCard from './components/MovieCard.jsx';</code>","why":"Correct. A default export is imported without curly braces, and you may name it anything (sticking to the same name is wise)."},{"text":"<code dir=\"ltr\">import { MovieCard } from './components/MovieCard.jsx';</code>","why":"Curly braces import a named export. This file only has a default export, so the import is <code dir=\"ltr\">undefined</code>."},{"text":"<code dir=\"ltr\">import MovieCard from 'MovieCard';</code>","why":"A bare name like ‘MovieCard’ is looked up in node_modules. Your own files need a relative path."}],"answer":0},{"q":"<p>A teammate defines <code dir=\"ltr\">Badge</code> inside <code dir=\"ltr\">MovieCard</code>. What problem does this cause?</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"jsx\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">JSX</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"Copy code\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>Copy</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">export</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> default</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> MovieCard</span><span style=\"color:#953800;--shiki-dark:#FFA657\">() </span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">{</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  function</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> Badge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">() {</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">span</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>New&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">span</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">  }</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">  return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> &#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>&#x3C;</span><span style=\"color:#116329;--shiki-dark:#7EE787\">Badge</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> />&#x3C;/</span><span style=\"color:#116329;--shiki-dark:#7EE787\">article</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">>;</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span></code></pre></div>\n","options":[{"text":"It’s a syntax error; functions can’t be nested in JSX files.","why":"Nested functions are valid JavaScript. The code runs; the problem shows up at runtime."},{"text":"<code dir=\"ltr\">Badge</code> can’t be exported, so tests can’t import it.","why":"That’s a minor downside. The real problem is what happens to Badge on every render."},{"text":"React renders <code dir=\"ltr\">Badge</code> twice, once for each function.","why":"Nothing renders twice here. The cost is that Badge is recreated from scratch."},{"text":"Every render of <code dir=\"ltr\">MovieCard</code> creates a brand-new <code dir=\"ltr\">Badge</code> function, so React throws away and rebuilds Badge’s DOM and state each time.","why":"Correct. React sees a different component type on every render and remounts it. Move <code dir=\"ltr\">Badge</code> to the top level of the module."}],"answer":3},{"q":"<p>Your App returns <code dir=\"ltr\">&lt;Header /&gt;&lt;MovieCard /&gt;</code> side by side and Vite shows “Adjacent JSX elements must be wrapped in an enclosing tag”. What’s the smallest correct fix?</p>","options":[{"text":"Return an array of the two components.","why":"An array renders, but React warns unless every item has a key, and it’s awkward for fixed markup. There’s a cleaner tool for this."},{"text":"Wrap them in a fragment, <code dir=\"ltr\">&lt;&gt;…&lt;/&gt;</code>, or in a meaningful element such as <code dir=\"ltr\">&lt;main&gt;</code>.","why":"Correct. A component returns one root. A fragment groups elements without adding a DOM node."},{"text":"Call each component as a function, <code dir=\"ltr\">Header()</code> and <code dir=\"ltr\">MovieCard()</code>, and join the results.","why":"Calling components as functions bypasses React’s rendering and breaks Hooks inside them. Always use JSX tags."}],"answer":1}],"exercise":{"kind":"web","mode":"react","starter":{"jsx":"function Header() {\n  // Return a <header> with an <h1> and a <p>\n  return null;\n}\n\nfunction MovieCard() {\n  // Return an <article> with an <h2> title and a <p> year\n  return null;\n}\n\nexport default function App() {\n  return (\n    <main>\n      {/* Use Header once and MovieCard twice */}\n    </main>\n  );\n}\n"},"solution":{"jsx":"function Header() {\n  return (\n    <header>\n      <h1>My Watchlist</h1>\n      <p>Movies I want to see</p>\n    </header>\n  );\n}\n\nfunction MovieCard() {\n  return (\n    <article>\n      <h2>Arrival</h2>\n      <p>2016</p>\n    </article>\n  );\n}\n\nexport default function App() {\n  return (\n    <main>\n      <Header />\n      <MovieCard />\n      <MovieCard />\n    </main>\n  );\n}\n"},"checks":[{"id":"header-heading","test":"return text('header h1') === 'My Watchlist';"},{"id":"header-tagline","test":"return text('header p').length > 0;"},{"id":"two-cards","test":"return $$('main article').length === 2;"},{"id":"card-content","test":"return $$('article').every((a) => a.querySelector('h2') && a.querySelector('h2').textContent.includes('Arrival') && a.querySelector('p') && a.querySelector('p').textContent.includes('2016')) && $$('article').length > 0;"}],"title":"Header and movie cards","prompt":"<p>Build the first slice of the Watchlist screen.</p>\n<ol>\n<li>Make <code dir=\"ltr\">Header</code> return a <code dir=\"ltr\">&lt;header&gt;</code> containing an <code dir=\"ltr\">&lt;h1&gt;</code> with the text <strong>My Watchlist</strong> and a <code dir=\"ltr\">&lt;p&gt;</code> tagline of your choice.</li>\n<li>Make <code dir=\"ltr\">MovieCard</code> return an <code dir=\"ltr\">&lt;article&gt;</code> with an <code dir=\"ltr\">&lt;h2&gt;</code> reading <strong>Arrival</strong> and a <code dir=\"ltr\">&lt;p&gt;</code> reading <strong>2016</strong>.</li>\n<li>In <code dir=\"ltr\">App</code>, render <code dir=\"ltr\">Header</code> once and <code dir=\"ltr\">MovieCard</code> twice inside the <code dir=\"ltr\">&lt;main&gt;</code>.</li>\n</ol>\n","hints":["A component returns JSX, for example <code dir=\"ltr\">return (&lt;header&gt;…&lt;/header&gt;);</code>. Keep the parentheses so the return isn’t cut short.","Use components as tags with a capital letter: <code dir=\"ltr\">&lt;Header /&gt;</code>, <code dir=\"ltr\">&lt;MovieCard /&gt;</code>.","App should contain <code dir=\"ltr\">&lt;Header /&gt;</code>, <code dir=\"ltr\">&lt;MovieCard /&gt;</code> and <code dir=\"ltr\">&lt;MovieCard /&gt;</code> inside <code dir=\"ltr\">&lt;main&gt;</code>."],"explanation":"<p>Each component is a top-level function that returns one root element. <code dir=\"ltr\">App</code> composes them as tags, and React calls <code dir=\"ltr\">Header</code> once and <code dir=\"ltr\">MovieCard</code> twice, producing two identical <code dir=\"ltr\">&lt;article&gt;</code>s. The duplication is deliberate: in Section 2 you’ll pass each card its own movie with props.</p>\n","checkLabels":{"header-heading":"The <header> contains an <h1> reading “My Watchlist”","header-tagline":"The <header> has a <p> tagline","two-cards":"<main> contains exactly two <article> cards","card-content":"Each card has an <h2> with “Arrival” and a <p> with “2016”"}},"words":680,"readMinutes":3}