Getting Started

Quick Start

Build your first React component and understand the core concepts in 10 minutes.

Your First Component

React applications are built from components — reusable pieces of UI that manage their own state and render based on props. Let's build a simple counter component to understand the basics.

'use client';

import { useState } from 'react';

interface CounterProps {
  initialCount?: number;
  label?: string;
}

export default function Counter({ initialCount = 0, label = "Count" }: CounterProps) {
  const [count, setCount] = useState(initialCount);

  return (
    <div className="flex flex-col items-center gap-4 p-6 rounded-xl border border-gray-200">
      <h2 className="text-lg font-semibold text-gray-700">{label}</h2>
      <span className="text-5xl font-bold text-blue-600">{count}</span>
      <div className="flex gap-3">
        <button
          onClick={() => setCount(c => c - 1)}
          className="px-4 py-2 bg-red-100 text-red-600 rounded-lg hover:bg-red-200 transition-colors"
        >
          −
        </button>
        <button
          onClick={() => setCount(initialCount)}
          className="px-4 py-2 bg-gray-100 text-gray-600 rounded-lg hover:bg-gray-200 transition-colors"
        >
          Reset
        </button>
        <button
          onClick={() => setCount(c => c + 1)}
          className="px-4 py-2 bg-green-100 text-green-600 rounded-lg hover:bg-green-200 transition-colors"
        >
          +
        </button>
      </div>
    </div>
  );
}

Using the Component

Now that we have our Counter component, let's use it in a page. Components are composable — you can use them multiple times with different props.

import Counter from '@/components/Counter';

export default function HomePage() {
  return (
    <main className="min-h-screen flex flex-col items-center justify-center gap-8 p-8">
      <h1 className="text-4xl font-bold">My First React App</h1>

      <div className="flex flex-wrap gap-6 justify-center">
        <Counter label="Lives" initialCount={3} />
        <Counter label="Score" initialCount={0} />
        <Counter label="Level" initialCount={1} />
      </div>
    </main>
  );
}

Adding Side Effects

The useEffect hook lets you perform side effects in your components — like fetching data, updating the document title, or setting up subscriptions.

'use client';

import { useState, useEffect } from 'react';

export default function TitleUpdater() {
  const [count, setCount] = useState(0);

  // Update document title whenever count changes
  useEffect(() => {
    document.title = `Count: ${count} | My App`;

    // Cleanup function runs before next effect or unmount
    return () => {
      document.title = 'My App';
    };
  }, [count]); // Dependency array: re-run when count changes

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(c => c + 1)}>Increment</button>
    </div>
  );
}

The dependency array in useEffect controls when the effect re-runs. An empty array [] means the effect only runs once on mount.

Fetching Data

In Next.js App Router, you can fetch data directly in Server Components without useEffect. This is more efficient and secure.

// This is a Server Component — runs on the server
// No 'use client' needed, no useEffect needed

interface User {
  id: number;
  name: string;
  email: string;
}

async function getUsers(): Promise<User[]> {
  const res = await fetch('https://jsonplaceholder.typicode.com/users', {
    next: { revalidate: 3600 } // Cache for 1 hour
  });

  if (!res.ok) throw new Error('Failed to fetch users');
  return res.json();
}

export default async function UsersPage() {
  const users = await getUsers();

  return (
    <div className="container mx-auto p-8">
      <h1 className="text-3xl font-bold mb-6">Users</h1>
      <ul className="space-y-3">
        {users.map(user => (
          <li key={user.id} className="p-4 bg-white rounded-lg shadow">
            <p className="font-semibold">{user.name}</p>
            <p className="text-gray-500 text-sm">{user.email}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}