Bobby Encoded
PostsAbout
PostsAbout

© 2026 Bobby Jose

← Back to Blog

React Foundations: JSX, Components, and Props

March 1, 2025 · 7 min read

React, JavaScript, Frontend, Fundamentals, Interview Prep

Introduction

React has dominated the frontend landscape for good reason - its component-based architecture and declarative approach make building complex UIs manageable. This is the first in a 10-part series covering everything you need to know for building production React applications.

This article covers the absolute foundations: JSX, components, and props. These concepts might seem basic, but truly understanding the fundamentals separates good developers from great ones.


JSX: JavaScript's UI Syntax Extension

JSX looks like HTML but compiles to JavaScript function calls. Understanding this transformation is crucial.

// What you write
const element = <h1 className="title">Hello, World!</h1>;

// What React sees after compilation (React 17+)
import { jsx as _jsx } from 'react/jsx-runtime';
const element = _jsx('h1', { className: 'title', children: 'Hello, World!' });

Key JSX Rules

// 1. Single root element (use fragments to avoid extra DOM nodes)
function Card() {
  return (
    <>
      <h2>Title</h2>
      <p>Content</p>
    </>
  );
}

// 2. Close all tags
<img src="photo.jpg" />
<input type="text" />

// 3. camelCase for HTML attributes
<div className="container" tabIndex={0} onClick={handleClick}>
  <label htmlFor="email">Email</label>
</div>

// 4. JavaScript expressions in curly braces
const name = "World";
<h1>Hello, {name}!</h1>
<p>Sum: {2 + 2}</p>
<div style={{ color: 'blue', fontSize: '16px' }}>Styled text</div>

Key Insight

When asked "What is JSX?", a strong answer explains that JSX is syntactic sugar for React.createElement() (or the newer jsx-runtime). It's not HTML - it's JavaScript that looks like markup. This distinction shows you understand what's happening under the hood.

Conditional Rendering

function Greeting({ isLoggedIn, username }) {
  // Ternary for either/or
  return (
    <div>
      {isLoggedIn ? (
        <h1>Welcome back, {username}!</h1>
      ) : (
        <h1>Please sign in</h1>
      )}
    </div>
  );
}

// Short-circuit for conditional display
function Notification({ hasUnread, count }) {
  return (
    <div>
      {hasUnread && <span className="badge">{count}</span>}
    </div>
  );
}

Common Gotcha

Be careful with {count && <Component />} when count might be 0. Zero is falsy but React will render it as "0". Use {count > 0 && <Component />} instead.


Functional Components

Modern React is all about functional components. They're just JavaScript functions that return JSX.

// Simple component
function Welcome({ name }) {
  return <h1>Hello, {name}!</h1>;
}

// Arrow function syntax (equally valid)
const Welcome = ({ name }) => <h1>Hello, {name}!</h1>;

// Usage
<Welcome name="Alice" />

Component Composition

The power of React lies in composing small components into larger UIs:

function App() {
  return (
    <Layout>
      <Header />
      <main>
        <Sidebar />
        <Content>
          <ArticleList />
        </Content>
      </main>
      <Footer />
    </Layout>
  );
}

Real-World Example

When building Glucoplate, a nutrition tracking app, component composition made the dashboard manageable. Breaking it into independent, testable pieces meant features could evolve separately. This pattern scales well as apps grow.


Props: Component Communication

Props are how data flows down the component tree. They're read-only - never mutate props.

// Receiving props
function UserCard({ name, email, avatar, isOnline }) {
  return (
    <div className="user-card">
      <img src={avatar} alt={name} />
      <h3>{name}</h3>
      <p>{email}</p>
      {isOnline && <span className="online-badge">Online</span>}
    </div>
  );
}

// Passing props
<UserCard
  name="John Doe"
  email="john@example.com"
  avatar="/avatars/john.jpg"
  isOnline={true}
/>

Default Props

function Button({ variant = 'primary', size = 'medium', children }) {
  return (
    <button className={`btn btn-${variant} btn-${size}`}>
      {children}
    </button>
  );
}

// Uses defaults
<Button>Click me</Button>

// Overrides defaults
<Button variant="danger" size="large">Delete</Button>

The Children Prop

The children prop enables component composition:

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

// Usage - anything between tags becomes children
<Card title="User Profile">
  <UserAvatar />
  <UserInfo />
  <ActionButtons />
</Card>

Spreading Props

function Input({ label, error, ...inputProps }) {
  return (
    <div className="form-field">
      <label>{label}</label>
      <input {...inputProps} className={error ? 'error' : ''} />
      {error && <span className="error-message">{error}</span>}
    </div>
  );
}

// All standard input attributes work
<Input
  label="Email"
  type="email"
  placeholder="Enter email"
  required
  error={errors.email}
/>

Lists and Keys

Rendering lists is fundamental, and getting keys right is essential for performance.

function TodoList({ todos }) {
  return (
    <ul>
      {todos.map(todo => (
        <li key={todo.id}>
          <span>{todo.text}</span>
          <span>{todo.completed ? '✓' : '○'}</span>
        </li>
      ))}
    </ul>
  );
}

Keys Matter

Never use array index as key for dynamic lists. Keys help React identify which items changed, were added, or removed. Using index causes bugs when items are reordered or deleted.

// ❌ BAD - index as key
{items.map((item, index) => <Item key={index} {...item} />)}

// ✅ GOOD - stable unique identifier
{items.map(item => <Item key={item.id} {...item} />)}

Questions Worth Considering

Q1: What is JSX and how does it work?

Answer: JSX is a syntax extension for JavaScript that looks like HTML but compiles to JavaScript. When you write <div>Hello</div>, it transforms to React.createElement('div', null, 'Hello') or the newer jsx-runtime equivalent. This means JSX is just syntactic sugar - you could write React without it, but it makes component structure much clearer.

Q2: What's the difference between props and state?

Answer:

  • Props are passed from parent to child, are read-only, and the component cannot modify them
  • State is internal to a component, can be changed, and triggers re-renders when updated

Props flow down, state is local. When state in a parent changes, it can pass new props to children.

Q3: Why do we need keys in lists?

Answer: Keys help React's reconciliation algorithm identify which elements changed between renders. Without proper keys, React may:

  • Re-render more elements than necessary (performance issue)
  • Lose component state when items are reordered
  • Cause bugs with form inputs maintaining wrong values

Keys should be stable, unique identifiers - typically database IDs. Never use array indices for lists that can change.

Q4: Can you modify props inside a component?

Answer: No. Props are read-only. Attempting to modify them violates React's unidirectional data flow principle. If you need to change data based on props, either:

  • Lift state up to the parent and pass a callback to update it
  • Use local state derived from props (with useState or useMemo)

Common Mistakes

1. Mutating Props

// ❌ WRONG - never do this
function BadComponent({ user }) {
  user.name = 'Modified'; // Mutating prop!
  return <span>{user.name}</span>;
}

// ✅ CORRECT - create new object if needed
function GoodComponent({ user }) {
  const displayName = user.name.toUpperCase();
  return <span>{displayName}</span>;
}

2. Forgetting Key in Lists

// ❌ Warning: Each child should have a unique "key" prop
{items.map(item => <Item {...item} />)}

// ✅ CORRECT
{items.map(item => <Item key={item.id} {...item} />)}

3. Using Index as Key for Dynamic Lists

// ❌ BAD for lists that can change
{items.map((item, i) => <Item key={i} {...item} />)}

// ✅ GOOD - use stable ID
{items.map(item => <Item key={item.id} {...item} />)}

Summary

  • JSX is JavaScript syntax that looks like HTML, compiling to React.createElement calls
  • Components are functions that return JSX, enabling reusable UI pieces
  • Props pass data down the component tree and are read-only
  • Keys must be unique and stable for list items - never use array indices for dynamic lists
  • Children prop enables powerful composition patterns

These fundamentals are essential for any React developer. In the next part, we'll dive into State and Hooks - where React really comes alive.


Part 1 of the React Developer Reference series.

← Previous

React State and Hooks: The Complete Guide

Next →

Choosing a React Framework in 2025: A Solo Developer's Hard-Earned Lessons