{"id":951,"date":"2024-09-26T14:44:18","date_gmt":"2024-09-26T14:44:18","guid":{"rendered":"https:\/\/algocademy.com\/blog\/unlocking-the-power-of-react-components-a-beginners-guide-to-building-dynamic-user-interfaces\/"},"modified":"2026-10-15T12:51:16","modified_gmt":"2026-10-15T12:51:16","slug":"unlocking-the-power-of-react-components-a-beginners-guide-to-building-dynamic-user-interfaces","status":"publish","type":"post","link":"https:\/\/algocademy.com\/blog\/unlocking-the-power-of-react-components-a-beginners-guide-to-building-dynamic-user-interfaces\/","title":{"rendered":"React Components for Beginners: JSX, Props, State and Hooks"},"content":{"rendered":"<p>A React component is a JavaScript function that returns a piece of user interface written in JSX. You build a page by combining small components, passing data into them with props, and giving them memory with state. This guide covers the official way to learn that today: <a href=\"https:\/\/react.dev\/learn\">react.dev\/learn<\/a>, function components and hooks. It does not use Create React App, which React has deprecated.<\/p>\n<h2>Set up a project in five minutes<\/h2>\n<p>You need Node.js installed (check with <code>node -v<\/code>). For a real product, react.dev recommends starting with a framework such as Next.js, React Router or Expo, because they solve routing and data fetching for you. For learning the basics, react.dev also documents building from a build tool, and names Vite as one option. Vite gives you a plain client-side app with nothing else to learn:<\/p>\n<pre><code class=\"language-bash\">npm create vite@latest my-app -- --template react\ncd my-app\nnpm install\nnpm run dev\n<\/code><\/pre>\n<p>The last command prints a local address (usually <code>http:\/\/localhost:5173<\/code>). Open it and you see the starter page, which reloads whenever you save a file. The files you will edit are <code>src\/App.jsx<\/code> and <code>src\/main.jsx<\/code>. Delete the starter content in <code>App.jsx<\/code> and you are ready for the examples below.<\/p>\n<p>Create React App is deprecated, as react.dev&#8217;s installation page says, so tutorials that begin with <code>npx create-react-app<\/code> are out of date. Also skip <code>ReactDOM.render<\/code>: current React uses <code>createRoot<\/code>, which Vite&#8217;s <code>main.jsx<\/code> already sets up for you.<\/p>\n<h2>What a component is<\/h2>\n<p>A component is a function whose name starts with a capital letter and that returns JSX. Here is the smallest useful one:<\/p>\n<pre><code class=\"language-javascript\">function Greeting({ name, excited = false }) {\n  return &lt;h1&gt;Hello, {name}{excited ? '!' : '.'}&lt;\/h1&gt;;\n}\n<\/code><\/pre>\n<p>You use it like an HTML tag: <code>&lt;Greeting name=\"React\" excited \/&gt;<\/code> renders <code>&lt;h1&gt;Hello, React!&lt;\/h1&gt;<\/code>. The capital letter matters. React treats <code>&lt;greeting \/&gt;<\/code> as an HTML element and <code>&lt;Greeting \/&gt;<\/code> as your component.<\/p>\n<p>Older tutorials also show class components (<code>class Greeting extends React.Component<\/code>). They still work, but new code uses function components and hooks, and react.dev&#8217;s docs teach only those. You will meet classes mainly in older codebases.<\/p>\n<h2>JSX in practice<\/h2>\n<p>JSX looks like HTML but is JavaScript. A build tool (Vite does this for you) turns it into function calls. The rules that trip up beginners:<\/p>\n<ul>\n<li><strong>Return one root.<\/strong> Wrap siblings in a parent element or in an empty fragment, <code>&lt;&gt;...&lt;\/&gt;<\/code>.<\/li>\n<li><strong>Close every tag.<\/strong> <code>&lt;img \/&gt;<\/code>, <code>&lt;input \/&gt;<\/code> and <code>&lt;br \/&gt;<\/code> need the slash.<\/li>\n<li><strong>Use <code>className<\/code>, not <code>class<\/code><\/strong>, and camelCase attributes such as <code>onClick<\/code> and <code>htmlFor<\/code>.<\/li>\n<li><strong>Curly braces run JavaScript expressions:<\/strong> <code>{name}<\/code>, <code>{2 + 2}<\/code>, <code>{items.length}<\/code>. You can put expressions there, not statements such as <code>if<\/code>. Use a ternary (<code>cond ? a : b<\/code>) or <code>cond &amp;&amp; &lt;X \/&gt;<\/code> for conditional output.<\/li>\n<\/ul>\n<p>Careful with <code>cond &amp;&amp; ...<\/code> when <code>cond<\/code> is a number: <code>{items.length &amp;&amp; &lt;List \/&gt;}<\/code> renders a literal <code>0<\/code> when the list is empty. Write <code>items.length &gt; 0 &amp;&amp; ...<\/code> instead.<\/p>\n<h2>Props: data flowing down<\/h2>\n<p>Props are the inputs of a component, passed like HTML attributes. The component reads them from its parameter, usually destructured as above. Props are read-only: a component must never modify them. Data flows one way, from parent to child.<\/p>\n<p>A special prop, <code>children<\/code>, holds whatever you put between the opening and closing tags, which is how you build wrappers:<\/p>\n<pre><code class=\"language-javascript\">function Card({ title, children }) {\n  return (\n    &lt;section className=\"card\"&gt;\n      &lt;h2&gt;{title}&lt;\/h2&gt;\n      {children}\n    &lt;\/section&gt;\n  );\n}\n<\/code><\/pre>\n<p>Now <code>&lt;Card title=\"Tasks\"&gt;...anything...&lt;\/Card&gt;<\/code> wraps any content in the same markup. This is the main reuse tool in React.<\/p>\n<h2>Rendering lists and the key prop<\/h2>\n<p>Turn an array into elements with <code>map<\/code>, and give each item a <code>key<\/code> that is unique among its siblings and stable over time. React uses keys to tell which item is which when the list changes.<\/p>\n<pre><code class=\"language-javascript\">const tasks = [\n  { id: 1, text: 'Read the docs', done: true },\n  { id: 2, text: 'Build a component', done: false },\n];\n\nfunction TaskList({ items }) {\n  return (\n    &lt;ul&gt;\n      {items.map(task =&gt; (\n        &lt;li key={task.id}&gt;\n          {task.done ? '[x] ' : '[ ] '}{task.text}\n        &lt;\/li&gt;\n      ))}\n    &lt;\/ul&gt;\n  );\n}\n<\/code><\/pre>\n<p>Use an id from your data. Array indexes as keys cause wrong behavior when items are reordered, inserted or deleted, because the key then follows the position instead of the item.<\/p>\n<h2>State: a component&#8217;s memory<\/h2>\n<p>Props come from outside. State is data a component owns and that changes over time. You create it with the <code>useState<\/code> hook, which returns the current value and a function to update it:<\/p>\n<pre><code class=\"language-javascript\">import { useState } from 'react';\n\nfunction LikeButton() {\n  const [likes, setLikes] = useState(0);\n  return (\n    &lt;button onClick={() =&gt; setLikes(likes + 1)}&gt;\n      Likes: {likes}\n    &lt;\/button&gt;\n  );\n}\n<\/code><\/pre>\n<p>Clicking calls <code>setLikes<\/code>; React then calls <code>LikeButton<\/code> again with the new value and updates the page. Run in a test page, this renders <code>Likes: 0<\/code>, and after two clicks the button reads <code>Likes: 2<\/code>.<\/p>\n<p>Two rules cover most beginner bugs:<\/p>\n<ul>\n<li><strong>Never change state directly.<\/strong> <code>likes++<\/code> or <code>list.push(x)<\/code> will not update the screen. Call the setter with a new value, and for arrays and objects pass a new copy: <code>setItems([...items, newItem])<\/code>.<\/li>\n<li><strong>Hooks go at the top level<\/strong> of a component, never inside <code>if<\/code>, loops or nested functions, so React sees them in the same order on every render.<\/li>\n<\/ul>\n<h2>Sharing state: lift it up<\/h2>\n<p>When two components need the same data, move the state to their closest common parent and pass the value and a callback down as props:<\/p>\n<pre><code class=\"language-javascript\">import { useState } from 'react';\n\nfunction Counter({ count, onIncrement }) {\n  return &lt;button onClick={onIncrement}&gt;Clicked {count} times&lt;\/button&gt;;\n}\n\nexport default function App() {\n  const [count, setCount] = useState(0);\n  return (\n    &lt;&gt;\n      &lt;Counter count={count} onIncrement={() =&gt; setCount(count + 1)} \/&gt;\n      &lt;Counter count={count} onIncrement={() =&gt; setCount(count + 1)} \/&gt;\n      &lt;p&gt;Total: {count}&lt;\/p&gt;\n    &lt;\/&gt;\n  );\n}\n<\/code><\/pre>\n<p>Both buttons and the total stay in sync because there is a single source of truth. Clicking one button twice changes both labels to <code>Clicked 2 times<\/code> and the total to 2.<\/p>\n<h2>Effects and what replaced lifecycle methods<\/h2>\n<p>Class components had <code>componentDidMount<\/code> and <code>componentWillUnmount<\/code>. In function components, <code>useEffect<\/code> covers the case of synchronizing with something outside React, such as a timer, a subscription or a browser API. Do not reach for it for everything: if you can compute a value from props and state during rendering, do that instead, and handle clicks in event handlers. react.dev has a page called &#8220;You Might Not Need an Effect&#8221; that is worth reading once you use effects. Our post on <a href=\"https:\/\/algocademy.com\/blog\/unlocking-the-power-of-react-hooks-a-comprehensive-guide-for-developers\/\">React hooks<\/a> goes further into <code>useEffect<\/code> and others.<\/p>\n<h2>Common beginner mistakes<\/h2>\n<ul>\n<li><strong>Lowercase component names.<\/strong> <code>&lt;card \/&gt;<\/code> becomes an unknown HTML tag.<\/li>\n<li><strong>Defining a component inside another component.<\/strong> It is re-created on every render and loses its state. Declare components at the top level of the file.<\/li>\n<li><strong>Calling the handler instead of passing it.<\/strong> <code>onClick={handle()}<\/code> runs during render; write <code>onClick={handle}<\/code> or <code>onClick={() =&gt; handle(id)}<\/code>.<\/li>\n<li><strong>Expecting state to update immediately.<\/strong> After <code>setLikes(likes + 1)<\/code>, the variable <code>likes<\/code> still holds the old value for the rest of that render. The new value shows up on the next render.<\/li>\n<li><strong>Missing or duplicate keys<\/strong> in lists, which shows up as a console warning.<\/li>\n<\/ul>\n<h2>Where to go next<\/h2>\n<p>Work through the official tutorial and the &#8220;Learn React&#8221; section on <a href=\"https:\/\/react.dev\/learn\">react.dev<\/a>, and rebuild a small app of your own, such as a to-do list or a quiz, without copying. Then add a data fetch, routing, and a framework. If you are still choosing a front-end library, see <a href=\"https:\/\/algocademy.com\/blog\/vue-vs-react-a-detailed-comparison-for-frontend-developers\/\">Vue vs React<\/a>. React is JavaScript first, so solid JavaScript (arrays, <code>map<\/code>, destructuring, closures) is what makes it feel easy. You can practice general problem solving with step-by-step guidance at <a href=\"https:\/\/app.algocademy.com\/\">app.algocademy.com<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Learn what React components are, how JSX, props and state work, and how to start a project with Vite, with small examples that run.<\/p>\n","protected":false},"author":1,"featured_media":949,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[23],"tags":[],"class_list":["post-951","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-problem-solving"],"_links":{"self":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/951"}],"collection":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/comments?post=951"}],"version-history":[{"count":3,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/951\/revisions"}],"predecessor-version":[{"id":8937,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/posts\/951\/revisions\/8937"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media\/949"}],"wp:attachment":[{"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/media?parent=951"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/categories?post=951"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/algocademy.com\/blog\/wp-json\/wp\/v2\/tags?post=951"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}