Week 4 - React Fundamentals

Why React?

Setting up a React project with Vite

Components

JSX

Props

Rendering lists

Conditional rendering

The mental model: how React renders (2)

Practice

Assignment

Front end Track

Props

Props — short for properties — are how you pass data from a parent component to a child. They work like HTML attributes, except the names are yours to define and the values can be any JavaScript type.

Props are what make components reusable. The same <UserCard /> can render hundreds of different users by receiving different data each time.

How Props Work

When you write <UserCard name="Wouter" age={32} />, React calls the UserCard function with a single argument: an object containing all the props you passed.

// React calls it like this internally:
UserCard({ name: 'Wouter', age: 32 });

You can receive that object as props and access values from it:

function UserCard(props) {
  return <h3>{props.name} is {props.age}</h3>;
}

In practice, you'll always destructure in the function signature:

function UserCard({ name, age }) {
  return <h3>{name} is {age}</h3>;
}

Same result, less noise. Destructuring is what you'll see in virtually every real codebase.

Passing Different Types

Strings can use quotes. Everything else uses curly braces.

<UserCard
  name="Wouter"                        // string — quotes
  age={32}                             // number — braces
  isOnline={true}                      // boolean — braces
  hobbies={['chess', 'ramen']}         // array — braces
  address={{ city: 'Amsterdam' }}      // object — braces (note the double {{}})
  onClick={handleClick}                // function — braces
/>

When in doubt, use {}. The only thing quotes are shorthand for is strings.

<aside> ⚠️

Warning

A few mistakes you'll make at least once:

Default Values

You can give props default values directly in the destructuring:

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

<Button />                             // "Click me", blue
<Button label="Save" />               // "Save", blue
<Button label="Delete" color="red" /> // "Delete", red

<aside> 💡

Info

Default values only apply when the prop is undefined — when the parent didn't pass it at all. Passing label={undefined} triggers the default. Passing label={null} does not.

</aside>

The Children Prop

Anything between a component's opening and closing tags is automatically passed as a special prop called children:

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

<Card>
  <h2>Hello</h2>
  <p>This content is passed as children.</p>
</Card>

The <h2> and <p> become children. This is the pattern behind layout components — cards, modals, page wrappers, anything that needs to wrap arbitrary content without caring what's inside.

<aside> ⌨️

Hands On

Build a Section component that renders a <section> with a heading and whatever children are passed in:

<Section title="Featured Products">
  <p>Some content here</p>
</Section>

The title should render as an <h2> inside the section. The children should render below it.

</aside>

A Complete Example

function UserCard({ name, role, isOnline, avatarUrl }) {
  return (
    <div className="user-card">
      <img src={avatarUrl} alt={name} width={48} />
      <div>
        <h3>{name}</h3>
        <p>Role: {role}</p>
        <p>Status: {isOnline ? '🟢 Online' : '⚪ Offline'}</p>
      </div>
    </div>
  );
}

function App() {
  return (
    <div>
      <h1>Team</h1>
      <UserCard
        name="Wouter"
        role="Mentor"
        isOnline={true}
        avatarUrl="<https://i.pravatar.cc/48?u=wouter>"
      />
      <UserCard
        name="Noer"
        role="Trainee"
        isOnline={false}
        avatarUrl="<https://i.pravatar.cc/48?u=noer>"
      />
      <UserCard
        name="Federico"
        role="Mentor"
        isOnline={true}
        avatarUrl="<https://i.pravatar.cc/48?u=federico>"
      />
    </div>
  );
}

One component definition. Three different users. That's props doing their job.

Spreading Props

When your data already lives in an object, you can spread it directly onto a component instead of listing each prop manually:

const user = { name: 'Wouter', role: 'Mentor', isOnline: true, avatarUrl: '...' };

<UserCard {...user} />

This becomes especially useful when you're mapping over an array of objects — which is exactly what you'll do in the next lesson.

TypeScript: Typing Your Props

TypeScript lets you define exactly which props a component expects and what types they should be. You do this with an interface:

interface UserCardProps {
  name: string;
  role: string;
  isOnline: boolean;
  avatarUrl: string;
}

function UserCard({ name, role, isOnline, avatarUrl }: UserCardProps) {
  return (
    <div className="user-card">
      <img src={avatarUrl} alt={name} width={48} />
      <div>
        <h3>{name}</h3>
        <p>Role: {role}</p>
        <p>Status: {isOnline ? '🟢 Online' : '⚪ Offline'}</p>
      </div>
    </div>
  );
}

Now if you forget a required prop or pass the wrong type, TypeScript tells you immediately in your editor — before you run anything.

For optional props, use ?:

interface ButtonProps {
  label: string;
  color?: string; // optional — has a default value
}

<aside> 💡

Info

Naming the interface after the component with Props at the end (UserCardProps, ButtonProps) is the standard convention. You'll see it everywhere in TypeScript React codebases.

</aside>

Props Are Read-Only

Props flow one way: from parent to child. A component cannot modify the props it receives.

function Bad({ count }) {
  count = count + 1; // ❌ Don't do this
  return <p>{count}</p>;
}

If you need data to change over time, that's what state is for. You'll meet useState in week 8 and it will make this constraint click into place.

<aside> 🎉

Celebration

Props are the backbone of component communication in React. You now know how to make components reusable, how to type them with TypeScript, and how the children pattern works. That's most of what you'll use props for across the entire course.

</aside>

Additional Resources

Videos

Reading

Interactive


The HackYourFuture curriculum is licensed under CC BY-NC-SA 4.0 *https://hackyourfuture.net/*

CC BY-NC-SA 4.0 Icons

Built with ❤️ by the HackYourFuture community · Thank you, contributors

Found a mistake or have a suggestion? Let us know in the feedback form.