Blog

React Components for Beginners: JSX, Props, State and Hooks

Developer coding on a laptop with colorful sticky notes.

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: react.dev/learn, function components and hooks. It does not use Create React App, which React has deprecated.

Set up a project in five minutes

You need Node.js installed (check with node -v). 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:

npm create vite@latest my-app -- --template react
cd my-app
npm install
npm run dev

The last command prints a local address (usually http://localhost:5173). Open it and you see the starter page, which reloads whenever you save a file. The files you will edit are src/App.jsx and src/main.jsx. Delete the starter content in App.jsx and you are ready for the examples below.

Create React App is deprecated, as react.dev’s installation page says, so tutorials that begin with npx create-react-app are out of date. Also skip ReactDOM.render: current React uses createRoot, which Vite’s main.jsx already sets up for you.

What a component is

A component is a function whose name starts with a capital letter and that returns JSX. Here is the smallest useful one:

function Greeting({ name, excited = false }) {
  return <h1>Hello, {name}{excited ? '!' : '.'}</h1>;
}

You use it like an HTML tag: <Greeting name="React" excited /> renders <h1>Hello, React!</h1>. The capital letter matters. React treats <greeting /> as an HTML element and <Greeting /> as your component.

Older tutorials also show class components (class Greeting extends React.Component). They still work, but new code uses function components and hooks, and react.dev’s docs teach only those. You will meet classes mainly in older codebases.

JSX in practice

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:

  • Return one root. Wrap siblings in a parent element or in an empty fragment, <>...</>.
  • Close every tag. <img />, <input /> and <br /> need the slash.
  • Use className, not class, and camelCase attributes such as onClick and htmlFor.
  • Curly braces run JavaScript expressions: {name}, {2 + 2}, {items.length}. You can put expressions there, not statements such as if. Use a ternary (cond ? a : b) or cond && <X /> for conditional output.

Careful with cond && ... when cond is a number: {items.length && <List />} renders a literal 0 when the list is empty. Write items.length > 0 && ... instead.

Props: data flowing down

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.

A special prop, children, holds whatever you put between the opening and closing tags, which is how you build wrappers:

function Card({ title, children }) {
  return (
    <section className="card">
      <h2>{title}</h2>
      {children}
    </section>
  );
}

Now <Card title="Tasks">...anything...</Card> wraps any content in the same markup. This is the main reuse tool in React.

Rendering lists and the key prop

Turn an array into elements with map, and give each item a key that is unique among its siblings and stable over time. React uses keys to tell which item is which when the list changes.

const tasks = [
  { id: 1, text: 'Read the docs', done: true },
  { id: 2, text: 'Build a component', done: false },
];

function TaskList({ items }) {
  return (
    <ul>
      {items.map(task => (
        <li key={task.id}>
          {task.done ? '[x] ' : '[ ] '}{task.text}
        </li>
      ))}
    </ul>
  );
}

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.

State: a component’s memory

Props come from outside. State is data a component owns and that changes over time. You create it with the useState hook, which returns the current value and a function to update it:

import { useState } from 'react';

function LikeButton() {
  const [likes, setLikes] = useState(0);
  return (
    <button onClick={() => setLikes(likes + 1)}>
      Likes: {likes}
    </button>
  );
}

Clicking calls setLikes; React then calls LikeButton again with the new value and updates the page. Run in a test page, this renders Likes: 0, and after two clicks the button reads Likes: 2.

Two rules cover most beginner bugs:

  • Never change state directly. likes++ or list.push(x) will not update the screen. Call the setter with a new value, and for arrays and objects pass a new copy: setItems([...items, newItem]).
  • Hooks go at the top level of a component, never inside if, loops or nested functions, so React sees them in the same order on every render.

Sharing state: lift it up

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:

import { useState } from 'react';

function Counter({ count, onIncrement }) {
  return <button onClick={onIncrement}>Clicked {count} times</button>;
}

export default function App() {
  const [count, setCount] = useState(0);
  return (
    <>
      <Counter count={count} onIncrement={() => setCount(count + 1)} />
      <Counter count={count} onIncrement={() => setCount(count + 1)} />
      <p>Total: {count}</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 Clicked 2 times and the total to 2.

Effects and what replaced lifecycle methods

Class components had componentDidMount and componentWillUnmount. In function components, useEffect 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 “You Might Not Need an Effect” that is worth reading once you use effects. Our post on React hooks goes further into useEffect and others.

Common beginner mistakes

  • Lowercase component names. <card /> becomes an unknown HTML tag.
  • Defining a component inside another component. It is re-created on every render and loses its state. Declare components at the top level of the file.
  • Calling the handler instead of passing it. onClick={handle()} runs during render; write onClick={handle} or onClick={() => handle(id)}.
  • Expecting state to update immediately. After setLikes(likes + 1), the variable likes still holds the old value for the rest of that render. The new value shows up on the next render.
  • Missing or duplicate keys in lists, which shows up as a console warning.

Where to go next

Work through the official tutorial and the “Learn React” section on react.dev, 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 Vue vs React. React is JavaScript first, so solid JavaScript (arrays, map, destructuring, closures) is what makes it feel easy. You can practice general problem solving with step-by-step guidance at app.algocademy.com.

A lesson in AlgoCademy: the step to write, a picture of what it does, the line written in the editor, and the check: Step 2 passed

Before you go

Start thinking like a software engineer.

Learn to code and solve interview problems, one small, checked step at a time.

Free, no card needed. Or look around first

By continuing you agree to the Terms of Service and Privacy Policy.