Beginner25 min read

Components & Props

Learn to build reusable React components, pass data with props, and compose components together to create complex UIs.

Function Components

In React, a component is a function that returns JSX. Components let you split your UI into independent, reusable pieces. Think of them like custom HTML elements that you define yourself.

A function component is simply a JavaScript function with two rules:

  1. The name must start with an uppercase letter. React uses this to distinguish components (<MyButton />) from regular HTML elements (<button>).
  2. It must return JSX (or null if it should render nothing).
jsx
function UserCard() {
  return (
    <div className="card">
      <h2>John Doe</h2>
      <p>Software Developer</p>
    </div>
  );
}

You can also write components as arrow functions:

jsx
const UserCard = () => (
  <div className="card">
    <h2>John Doe</h2>
    <p>Software Developer</p>
  </div>
);

Both styles are valid and functionally identical. The regular function syntax is slightly more common in React documentation and tutorials.

Once defined, you use a component like an HTML tag:

jsx
function App() {
  return (
    <div>
      <UserCard />
      <UserCard />
      <UserCard />
    </div>
  );
}

This renders three identical user cards. But identical cards are not very useful — we need a way to make each one different. That is where props come in.

Props: Passing Data to Components

Props (short for "properties") are the mechanism for passing data from a parent component to a child component. Props make components dynamic and reusable — the same component can render different content depending on the props it receives.

Props are passed as attributes in JSX, just like HTML attributes:

jsx
<UserCard name="Alice" role="Designer" />
<UserCard name="Bob" role="Developer" />

Inside the component, props are received as a single object parameter:

jsx
function UserCard(props) {
  return (
    <div className="card">
      <h2>{props.name}</h2>
      <p>{props.role}</p>
    </div>
  );
}

The props object for the first <UserCard> would be { name: 'Alice', role: 'Designer' }.

Destructuring props is the preferred pattern because it makes the code cleaner and immediately shows which props the component expects:

jsx
function UserCard({ name, role }) {
  return (
    <div className="card">
      <h2>{name}</h2>
      <p>{role}</p>
    </div>
  );
}

You can pass any JavaScript value as a prop — strings, numbers, booleans, arrays, objects, and even functions:

jsx
<ProductCard
  title="Laptop"
  price={999}
  inStock={true}
  tags={['electronics', 'sale']}
  onBuy={() => console.log('Bought!')}
/>

Note: String props use quotes, but all other types use curly braces {}.

Default Props and the Children Prop

Default values for props can be set using JavaScript's default parameter syntax:

jsx
function Button({ text = 'Click me', color = 'blue' }) {
  return (
    <button style={{ backgroundColor: color }}>
      {text}
    </button>
  );
}

// Uses defaults:
<Button />

// Overrides text:
<Button text="Submit" />

// Overrides both:
<Button text="Delete" color="red" />

The children prop is a special prop that contains whatever you put between the opening and closing tags of a component:

jsx
function Card({ children }) {
  return (
    <div className="card">
      {children}
    </div>
  );
}

// Usage:
<Card>
  <h2>Title</h2>
  <p>Some content goes here.</p>
</Card>

The children prop is powerful because it lets you create wrapper components — components that provide structure or styling while allowing any content inside. This pattern is used everywhere in React:

jsx
function Layout({ children }) {
  return (
    <div className="layout">
      <nav>Navigation</nav>
      <main>{children}</main>
      <footer>Footer</footer>
    </div>
  );
}

function App() {
  return (
    <Layout>
      <h1>Home Page</h1>
      <p>Welcome to my site!</p>
    </Layout>
  );
}

The children prop makes Layout reusable — you can wrap any content with the same navigation and footer.

Composing Components

React encourages you to break your UI into a tree of small, focused components. Each component should do one thing well. This is called composition.

Consider building a user profile page:

jsx
function Avatar({ src, alt }) {
  return <img src={src} alt={alt} className="avatar" />;
}

function UserInfo({ name, bio }) {
  return (
    <div>
      <h3>{name}</h3>
      <p>{bio}</p>
    </div>
  );
}

function ProfileCard({ user }) {
  return (
    <div className="profile-card">
      <Avatar src={user.avatar} alt={user.name} />
      <UserInfo name={user.name} bio={user.bio} />
    </div>
  );
}

function App() {
  const user = {
    name: 'Alice',
    bio: 'React developer',
    avatar: 'alice.jpg'
  };
  return <ProfileCard user={user} />;
}

Notice how each component is small and focused:

  • Avatar only handles displaying an image.
  • UserInfo only displays a name and bio.
  • ProfileCard composes them together.
  • App provides the data.

Important rules about props:

  1. Props are read-only. A component must never modify the props it receives. This is a fundamental rule in React.
  2. Data flows down. Props flow from parent to child, never the other way around. This unidirectional flow makes your app predictable.
  3. Props can be anything. Strings, numbers, arrays, objects, functions, even other components.
jsx
// Never do this — props are read-only!
function Bad(props) {
  props.name = 'hacked'; // This violates React's rules
  return <h1>{props.name}</h1>;
}

Components and Props in Action

html
<div id="root"></div>
<script src="https://unpkg.com/react@19/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@19/umd/react-dom.development.js"></script>
<script src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
<script type="text/babel">
  function Badge({ label, color = "gray" }) {
    return (
      <span style={{
        backgroundColor: color,
        color: "white",
        padding: "2px 8px",
        borderRadius: "4px",
        fontSize: "12px",
        marginRight: "4px"
      }}>
        {label}
      </span>
    );
  }

  function UserCard({ name, role, skills }) {
    return (
      <div style={{ border: "1px solid #ccc", padding: "16px", margin: "8px", borderRadius: "8px" }}>
        <h2>{name}</h2>
        <p>{role}</p>
        <div>
          {skills.map((skill, i) => (
            <Badge key={i} label={skill} color="#3b82f6" />
          ))}
        </div>
      </div>
    );
  }

  function App() {
    return (
      <div>
        <h1>Team</h1>
        <UserCard name="Alice" role="Frontend Dev" skills={["React", "CSS"]} />
        <UserCard name="Bob" role="Backend Dev" skills={["Node", "SQL"]} />
      </div>
    );
  }

  ReactDOM.createRoot(document.getElementById('root')).render(<App />);
</script>

What is the correct way to pass a number as a prop to a component?

Ready to practice?

Create your free account to access the interactive code editor, run challenges, and track your progress.