# React Fundamentals & Your First Component

When I started building the frontend for my multi-tenant POS system, I needed to display hundreds of products across different restaurant menus and retail catalogs. Each product needed to show its name, price, available stock, and category—all in a consistent, reusable way. This is where I learned that React's component model isn't just a nice-to-have; it's essential for building maintainable applications.

Instead of copying and pasting HTML for each product, I built a single `ProductCard` component that could be reused everywhere. This one decision saved me countless hours and made the entire application easier to maintain.

## What Are Components?

Components are the building blocks of React applications. Think of them as custom HTML elements that you define yourself. Just like you use `<button>` or `<input>` in HTML, in React you create components like `<ProductCard>` or `<ShoppingCart>`.

**In the POS system**, every piece of the UI is a component:

* The product card displaying item details
* The search bar filtering products
* The navigation menu
* The shopping cart
* Even the entire page is a component

## Your First Component: The Product Card

Let's build the most fundamental piece of the POS system—a component that displays a single product.

### Step 1: A Static Component

Here's the simplest version, with hardcoded data:

```typescript
// ProductCard.tsx
import React from 'react';

function ProductCard() {
  return (
    <div className="product-card">
      <h3>Mohinga</h3>
      <p className="price">3500 MMK</p>
      <p className="stock">In Stock: 24</p>
      <p className="category">Breakfast</p>
    </div>
  );
}

export default ProductCard;
```

**What's happening here?**

1. **Import React**: We need React to use JSX (more on that in a moment)
2. **Define a function**: Components are just JavaScript functions
3. **Return JSX**: This HTML-like syntax is JSX (JavaScript XML)
4. **Export the component**: So we can use it elsewhere

**Using the component:**

```typescript
// App.tsx
import React from 'react';
import ProductCard from './ProductCard';

function App() {
  return (
    <div className="app">
      <h1>Menu</h1>
      <ProductCard />
    </div>
  );
}

export default App;
```

Just like that, `<ProductCard />` renders our product. But there's a problem—every card shows the same hardcoded data.

## Understanding JSX

JSX looks like HTML, but it's actually JavaScript. When you write:

```typescript
<div className="product-card">
  <h3>Mohinga</h3>
</div>
```

React transforms it into:

```typescript
React.createElement('div', { className: 'product-card' },
  React.createElement('h3', null, 'Mohinga')
);
```

**Key differences from HTML:**

1. **`className` instead of `class`**: Because `class` is a reserved word in JavaScript
2. **Self-closing tags need `/`**: `<ProductCard />` not `<ProductCard>`
3. **JavaScript expressions in `{}`**: You can embed any JavaScript expression

```typescript
function ProductCard() {
  const productName = "Mohinga";
  const price = 3500;
  
  return (
    <div className="product-card">
      <h3>{productName}</h3>
      <p className="price">{price} MMK</p>
      <p className="total">Total with tax: {price * 1.05} MMK</p>
    </div>
  );
}
```

Anything inside `{}` is evaluated as JavaScript. You can use variables, call functions, perform calculations—anything that returns a value.

## Props: Making Components Reusable

The magic of components is **props** (short for properties). Props let you pass data into components, making them reusable with different data.

### Step 2: Component with Props

```typescript
// ProductCard.tsx
import React from 'react';

interface ProductCardProps {
  name: string;
  price: number;
  stock: number;
  category: string;
}

function ProductCard(props: ProductCardProps) {
  return (
    <div className="product-card">
      <h3>{props.name}</h3>
      <p className="price">{props.price} MMK</p>
      <p className="stock">In Stock: {props.stock}</p>
      <p className="category">{props.category}</p>
    </div>
  );
}

export default ProductCard;
```

**What changed?**

1. **Interface `ProductCardProps`**: TypeScript interface defining the shape of our props
2. **Function parameter `props`**: The component receives props as an argument
3. **Access props with dot notation**: `props.name`, `props.price`, etc.

**Using the component with different data:**

```typescript
// App.tsx
import React from 'react';
import ProductCard from './ProductCard';

function App() {
  return (
    <div className="app">
      <h1>Menu</h1>
      <ProductCard 
        name="Mohinga" 
        price={3500} 
        stock={24} 
        category="Breakfast" 
      />
      <ProductCard 
        name="Shan Noodles" 
        price={4000} 
        stock={15} 
        category="Lunch" 
      />
      <ProductCard 
        name="Tea Leaf Salad" 
        price={3000} 
        stock={0} 
        category="Appetizer" 
      />
    </div>
  );
}

export default App;
```

**Now we have three different products using the same component!** This is the power of props—write once, reuse everywhere.

### Destructuring Props (Cleaner Syntax)

Instead of writing `props.name`, `props.price` repeatedly, most React developers destructure props:

```typescript
// ProductCard.tsx
import React from 'react';

interface ProductCardProps {
  name: string;
  price: number;
  stock: number;
  category: string;
}

function ProductCard({ name, price, stock, category }: ProductCardProps) {
  return (
    <div className="product-card">
      <h3>{name}</h3>
      <p className="price">{price} MMK</p>
      <p className="stock">In Stock: {stock}</p>
      <p className="category">{category}</p>
    </div>
  );
}

export default ProductCard;
```

This is cleaner and more common in real codebases. The curly braces in the function parameter destructure the props object.

## Conditional Rendering

In the POS system, out-of-stock items need special treatment. Let's add conditional rendering:

```typescript
// ProductCard.tsx
import React from 'react';

interface ProductCardProps {
  name: string;
  price: number;
  stock: number;
  category: string;
}

function ProductCard({ name, price, stock, category }: ProductCardProps) {
  const isOutOfStock = stock === 0;
  
  return (
    <div className={`product-card ${isOutOfStock ? 'out-of-stock' : ''}`}>
      <h3>{name}</h3>
      <p className="price">{price} MMK</p>
      
      {isOutOfStock ? (
        <p className="stock-status out">Out of Stock</p>
      ) : (
        <p className="stock-status">In Stock: {stock}</p>
      )}
      
      <p className="category">{category}</p>
      
      {stock < 5 && stock > 0 && (
        <p className="warning">⚠️ Low Stock</p>
      )}
    </div>
  );
}

export default ProductCard;
```

**Conditional rendering techniques:**

1. **Ternary operator**: `condition ? <ComponentA /> : <ComponentB />`
2. **Logical AND**: `condition && <Component />` (renders component only if condition is true)
3. **Template literals for classes**: `` `product-card ${isOutOfStock ? 'out-of-stock' : ''}` ``

## Component Composition

Components can contain other components. Let's build a `ProductGrid` that contains multiple `ProductCard` components:

```typescript
// ProductGrid.tsx
import React from 'react';
import ProductCard from './ProductCard';

function ProductGrid() {
  return (
    <div className="product-grid">
      <ProductCard 
        name="Mohinga" 
        price={3500} 
        stock={24} 
        category="Breakfast" 
      />
      <ProductCard 
        name="Shan Noodles" 
        price={4000} 
        stock={15} 
        category="Lunch" 
      />
      <ProductCard 
        name="Tea Leaf Salad" 
        price={3000} 
        stock={0} 
        category="Appetizer" 
      />
    </div>
  );
}

export default ProductGrid;
```

This creates a hierarchy:

```
App
└── ProductGrid
    ├── ProductCard (Mohinga)
    ├── ProductCard (Shan Noodles)
    └── ProductCard (Tea Leaf Salad)
```

**This is component composition**—building complex UIs by composing simple components together.

## Adding Styles

React components can be styled in several ways. Here's how I styled the ProductCard in the POS system:

### Option 1: CSS Modules (Recommended for larger apps)

```typescript
// ProductCard.module.css
.productCard {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  padding: 16px;
  margin: 8px;
  background: white;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  transition: transform 0.2s;
}

.productCard:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
}

.productCard.outOfStock {
  opacity: 0.6;
  background: #f5f5f5;
}

.price {
  font-size: 1.25rem;
  font-weight: bold;
  color: #2e7d32;
  margin: 8px 0;
}

.stockStatus {
  font-size: 0.875rem;
  color: #666;
}

.stockStatus.out {
  color: #d32f2f;
  font-weight: bold;
}

.category {
  display: inline-block;
  background: #e3f2fd;
  color: #1976d2;
  padding: 4px 12px;
  border-radius: 12px;
  font-size: 0.75rem;
  margin-top: 8px;
}

.warning {
  color: #f57c00;
  font-size: 0.875rem;
  margin-top: 8px;
}
```

```typescript
// ProductCard.tsx
import React from 'react';
import styles from './ProductCard.module.css';

interface ProductCardProps {
  name: string;
  price: number;
  stock: number;
  category: string;
}

function ProductCard({ name, price, stock, category }: ProductCardProps) {
  const isOutOfStock = stock === 0;
  
  return (
    <div className={`${styles.productCard} ${isOutOfStock ? styles.outOfStock : ''}`}>
      <h3>{name}</h3>
      <p className={styles.price}>{price} MMK</p>
      
      {isOutOfStock ? (
        <p className={`${styles.stockStatus} ${styles.out}`}>Out of Stock</p>
      ) : (
        <p className={styles.stockStatus}>In Stock: {stock}</p>
      )}
      
      <p className={styles.category}>{category}</p>
      
      {stock < 5 && stock > 0 && (
        <p className={styles.warning}>⚠️ Low Stock</p>
      )}
    </div>
  );
}

export default ProductCard;
```

CSS Modules automatically scope styles to the component, preventing style conflicts.

## The Complete Picture: Types and Real Data

In the POS system, product data comes from the Inventory Service API. Here's how we'd type that properly:

```typescript
// types/product.ts
export interface Product {
  id: string;
  name: string;
  price: number;
  stock: number;
  category: string;
  description?: string; // Optional property
  imageUrl?: string;
}
```

```typescript
// ProductCard.tsx
import React from 'react';
import styles from './ProductCard.module.css';
import { Product } from './types/product';

interface ProductCardProps {
  product: Product;
}

function ProductCard({ product }: ProductCardProps) {
  const { name, price, stock, category, imageUrl } = product;
  const isOutOfStock = stock === 0;
  
  return (
    <div className={`${styles.productCard} ${isOutOfStock ? styles.outOfStock : ''}`}>
      {imageUrl && (
        <img src={imageUrl} alt={name} className={styles.productImage} />
      )}
      
      <h3>{name}</h3>
      <p className={styles.price}>{price.toLocaleString()} MMK</p>
      
      {isOutOfStock ? (
        <p className={`${styles.stockStatus} ${styles.out}`}>Out of Stock</p>
      ) : (
        <p className={styles.stockStatus}>In Stock: {stock}</p>
      )}
      
      <p className={styles.category}>{category}</p>
      
      {stock < 5 && stock > 0 && (
        <p className={styles.warning}>⚠️ Low Stock</p>
      )}
    </div>
  );
}

export default ProductCard;
```

**Key improvements:**

1. **Structured data**: Using a `Product` interface
2. **Optional properties**: `imageUrl?` means it might not exist
3. **Number formatting**: `.toLocaleString()` formats large numbers with commas
4. **Conditional image**: Only render `<img>` if `imageUrl` exists

## Key Learnings

After building hundreds of components in the POS system, here's what matters most:

### ✅ Components Are Just Functions

* They receive props as arguments
* They return JSX (which describes the UI)
* They can use any JavaScript logic inside

### ✅ Props Make Components Reusable

* Pass different data to the same component
* Define prop types with TypeScript interfaces
* Destructure props for cleaner code

### ✅ JSX Is JavaScript

* Use `{}` to embed any JavaScript expression
* `className` not `class`
* Conditional rendering with ternary or `&&` operators

### ✅ Composition Over Complexity

* Build small, focused components
* Compose them together to create complex UIs
* Each component should do one thing well

### ✅ TypeScript Saves Time

* Define interfaces for props to catch errors early
* Get autocomplete and IntelliSense in your editor
* Self-documenting code

## Common Mistakes I Made (So You Don't Have To)

**❌ Forgetting to export the component**

```typescript
function ProductCard() { ... }
// Missing: export default ProductCard;
```

**❌ Using `class` instead of `className`**

```typescript
<div class="card"> // ❌ Won't work
<div className="card"> // ✅ Correct
```

**❌ Forgetting curly braces for JavaScript expressions**

```typescript
<p>Price: price MMK</p> // ❌ Renders literal text "price"
<p>Price: {price} MMK</p> // ✅ Renders the value
```

**❌ Not typing props**

```typescript
function ProductCard(props) { ... } // ❌ No type safety
function ProductCard(props: ProductCardProps) { ... } // ✅ Type safe
```

## Next Steps

We've built a reusable `ProductCard` component, but it's still static. In the real POS system, I needed users to:

* Click "Add to Cart" buttons
* Increase/decrease quantities
* Respond to user interactions

That requires **state**—data that changes over time in response to user actions.

In the next article, we'll add interactivity to our components with `useState`, building an "Add to Cart" counter that actually works.

**Continue to**: [State & Interactivity](https://blog.htunnthuthu.com/getting-started/programming/react-101/react-101-state-interactivity)
