Skip to content
AyoKoding

Initial Setup

Want to start building with React? This initial setup guide gets React with TypeScript installed and working on your system in minutes. By the end, you'll have a React development environment configured and will create your first interactive component.

This tutorial provides 0-5% coverage - just enough to get React working on your machine. For deeper learning, continue to Quick Start (5-30% coverage).

Prerequisites

Before installing React, you need:

  • A computer running Windows, macOS, or Linux
  • Administrator/sudo access for installation
  • A terminal/command prompt
  • A code editor (VS Code recommended, but IntelliJ IDEA, WebStorm, Sublime Text work too)
  • Basic command-line navigation skills
  • Node.js 18+ installed (we'll verify this)
  • npm or pnpm package manager
  • Basic understanding of HTML, JavaScript, and CSS

No prior React or frontend framework experience required - this guide starts from zero.

Learning Objectives

By the end of this tutorial, you will be able to:

  1. Verify Node.js and npm installation
  2. Choose the right React setup method for your needs
  3. Create a new React application with TypeScript
  4. Understand the generated project structure
  5. Write your first React component
  6. Run the development server
  7. Build production-ready React applications

Verify Node.js Installation

React requires Node.js 18 or later.

node --version

Expected output:

v18.17.0

Required: Node.js 18.0.0 or later

Verify npm (Node Package Manager):

npm --version

Expected output:

9.6.7

If Node.js is not installed, follow the platform-specific instructions below.

Platform-Specific Node.js Installation

Windows Node.js Installation

Method 1: Official Installer (Recommended)

Step 1: Download Node.js Installer

  1. Visit https://nodejs.org/
  2. Download "LTS" version (Long Term Support)
  3. Select Windows Installer (.msi) for your architecture (64-bit recommended)

Step 2: Run Installer

  1. Double-click downloaded .msi file
  2. Follow installation wizard:
    • Click Next through license agreement
    • Keep default installation directory
    • Select "Automatically install necessary tools" checkbox
    • Click Install
    • Click Finish

Step 3: Verify Installation

Open Command Prompt or PowerShell:

node --version
npm --version

Method 2: Package Manager (Chocolatey)

choco install nodejs-lts

Troubleshooting Windows:

  • If node not found after installation, restart Command Prompt/PowerShell
  • Add C:\Program Files\nodejs to PATH if necessary
  • Run PowerShell as Administrator if permission errors occur

macOS Node.js Installation

Method 1: Homebrew (Recommended)

brew install node@18

Link the installed version:

brew link node@18

Method 2: Official Installer

  1. Visit https://nodejs.org/
  2. Download macOS Installer (.pkg) LTS version
  3. Run installer and follow prompts

Method 3: Node Version Manager (nvm)

# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
 
# Restart terminal or source profile
source ~/.zshrc  # or ~/.bash_profile
 
# Install Node.js 18
nvm install 18
nvm use 18
nvm alias default 18

Verify Installation:

node --version
npm --version

Troubleshooting macOS:

  • If node not found, ensure Homebrew's bin directory in PATH
  • For Apple Silicon (M1/M2), use Rosetta if compatibility issues arise
  • Restart terminal after installation

Linux Node.js Installation

Ubuntu/Debian

# Add NodeSource repository for Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
 
# Install Node.js
sudo apt update
sudo apt install nodejs

Fedora/RHEL/CentOS

# Add NodeSource repository
curl -fsSL https://rpm.nodesource.com/setup_18.x | sudo bash -
 
# Install Node.js
sudo dnf install nodejs

Arch Linux

sudo pacman -S nodejs npm

Using Node Version Manager (nvm) - All Distributions

# Install nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
 
# Reload shell configuration
source ~/.bashrc  # or ~/.zshrc
 
# Install Node.js 18
nvm install 18
nvm use 18
nvm alias default 18

Verify Installation:

node --version
npm --version

Troubleshooting Linux:

  • If permission errors occur, avoid using sudo with npm - use nvm instead
  • Ensure ~/.bashrc or ~/.zshrc sources nvm configuration
  • For build-essential dependencies: sudo apt install build-essential (Ubuntu/Debian)

React Installation Methods

React offers multiple setup approaches. Choose based on your needs:

Best for: Modern development, fast builds, learning React

Advantages:

  • Lightning-fast Hot Module Replacement (HMR)
  • Minimal configuration needed
  • Native ESM support
  • TypeScript out-of-the-box
  • Small bundle sizes

Use when: Starting a new React project, building SPAs (Single Page Applications)

Option 2: Next.js (Production-Ready Framework)

Best for: Production applications, SEO-critical sites, full-stack apps

Advantages:

  • Server-Side Rendering (SSR)
  • Static Site Generation (SSG)
  • API routes built-in
  • File-based routing
  • Optimized for production

Use when: Building production apps, needing SEO, requiring server-side features

Option 3: Create React App (Deprecated)

Status: No longer recommended by React team

Why avoid:

  • Slower build times than Vite
  • Heavyweight configuration
  • Less actively maintained
  • Superseded by Vite and Next.js

Do NOT use for new projects

Create Your First React App with Vite

We'll use Vite with TypeScript template - the recommended modern approach.

Generate New Project

npm create vite@latest

You'll see interactive prompts:

√ Project name: ... my-react-app
√ Select a framework: » React
√ Select a variant: » TypeScript

Configuration choices:

  • Project name: my-react-app (use lowercase with hyphens)
  • Framework: Select React
  • Variant: Select TypeScript (NOT TypeScript + SWC for beginners)

Output:

Scaffolding project in /path/to/my-react-app...

Done. Now run:

  cd my-react-app
  npm install
  npm run dev

Install Dependencies

cd my-react-app
npm install

Vite downloads React dependencies:

  • react - Core React library
  • react-dom - React rendering for web browsers
  • typescript - TypeScript compiler
  • vite - Build tool and dev server
  • @vitejs/plugin-react - Vite React plugin

This takes 30 seconds to 2 minutes depending on internet speed.

Output summary:

added 42 packages, and audited 43 packages in 15s

7 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Project Structure Walkthrough

Vite creates this structure:

my-react-app/
├── node_modules/         # Installed dependencies (don't edit)
├── public/               # Static assets (served as-is)
│   └── vite.svg         # Example static file
├── src/                  # Source code (your work goes here)
│   ├── assets/          # Images, fonts, etc.
│   │   └── react.svg
│   ├── App.css          # App component styles
│   ├── App.tsx          # Main App component
│   ├── index.css        # Global styles
│   ├── main.tsx         # Application entry point
│   └── vite-env.d.ts    # TypeScript Vite types
├── .gitignore           # Git ignore rules
├── index.html           # HTML entry point
├── package.json         # Project metadata and scripts
├── package-lock.json    # Dependency lock file
├── tsconfig.json        # TypeScript configuration
├── tsconfig.node.json   # TypeScript config for Node.js
└── vite.config.ts       # Vite configuration

Key Files Explained

index.html - HTML entry point (unique to Vite):

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>
  </body>
</html>

src/main.tsx - Application entry point:

import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
 
ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
)

src/App.tsx - Main application component:

import { useState } from 'react'
import reactLogo from './assets/react.svg'
import viteLogo from '/vite.svg'
import './App.css'
 
function App() {
  const [count, setCount] = useState(0)
 
  return (
    <>
      <div>
        <a href="https://vite.dev" target="_blank">
          <img src={viteLogo} className="logo" alt="Vite logo" />
        </a>
        <a href="https://react.dev" target="_blank">
          <img src={reactLogo} className="logo react" alt="React logo" />
        </a>
      </div>
      <h1>Vite + React</h1>
      <div className="card">
        <button onClick={() => setCount((count) => count + 1)}>
          count is {count}
        </button>
        <p>
          Edit <code>src/App.tsx</code> and save to test HMR
        </p>
      </div>
      <p className="read-the-docs">
        Click on the Vite and React logos to learn more
      </p>
    </>
  )
}
 
export default App

package.json - Project configuration:

{
  "name": "my-react-app",
  "private": true,
  "version": "0.0.0",
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@types/react": "^18.2.43",
    "@types/react-dom": "^18.2.17",
    "@vitejs/plugin-react": "^4.2.1",
    "typescript": "^5.2.2",
    "vite": "^5.0.8"
  }
}

Your First Component - Hello World

Let's modify App.tsx to create a simple Hello World component.

Replace App.tsx Content

Open src/App.tsx in your editor and replace everything with:

import { useState } from 'react'
import './App.css'
 
function App() {
  const [name, setName] = useState('World')
 
  return (
    <div className="App">
      <h1>Hello, {name}!</h1>
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter your name"
      />
      <p>Type in the input to see the greeting change!</p>
    </div>
  )
}
 
export default App

What this component does:

  • State management: Uses useState hook to track name value
  • Reactive rendering: Displays "Hello, {name}!" that updates automatically
  • User input: Text input controlled by React state
  • Event handling: onChange updates state when user types

Understanding the Code

import { useState } from 'react'  // Import React hook for state
import './App.css'                // Import component styles
 
function App() {                  // Functional component definition
  const [name, setName] = useState('World')
  // name: current state value (starts as 'World')
  // setName: function to update state
 
  return (                        // JSX return statement
    <div className="App">         {/* Root element */}
      <h1>Hello, {name}!</h1>     {/* Display dynamic value */}
      <input
        type="text"
        value={name}              {/* Controlled input */}
        onChange={(e) => setName(e.target.value)}  {/* Update on change */}
        placeholder="Enter your name"
      />
      <p>Type in the input to see the greeting change!</p>
    </div>
  )
}
 
export default App                // Export for use in main.tsx

Key React Concepts:

  • Components: JavaScript functions that return JSX
  • JSX: HTML-like syntax in JavaScript
  • State: Data that changes over time
  • Hooks: Functions that let you use React features (useState, etc.)
  • Props: Data passed from parent to child components (not shown here)

Run Development Server

Start the Server

npm run dev

Output:

  VITE v5.0.8  ready in 523 ms

  ➜  Local:   http://localhost:5173/
  ➜  Network: use --host to expose
  ➜  press h to show help

Server is ready at: http://localhost:5173/

Note: Port may differ if 5173 is occupied (Vite automatically finds an available port)

Access Your Application

Open browser and visit:

http://localhost:5173/

You should see:

  • Heading: "Hello, World!"
  • Text input with placeholder "Enter your name"
  • Description text below

Try it out:

  1. Type your name in the input field
  2. Watch the heading update in real-time
  3. Notice no page reload - this is React's reactive rendering!

Congratulations! Your first React component is working.

Hot Module Replacement (HMR)

Vite provides instant updates when you edit code.

Test HMR:

  1. Keep browser and terminal open
  2. Edit src/App.tsx - change "Hello" to "Welcome"
  3. Save file
  4. Browser updates instantly without full reload

This is HMR - updating only changed modules without losing state.

Stop the Server

Press Ctrl+C in terminal to stop development server.

Understanding the Build Process

React apps go through these stages:

Development Mode

npm run dev

What happens:

  1. Vite starts development server
  2. Serves source files with fast HMR
  3. TypeScript type-checking runs separately
  4. Source maps enabled for debugging
  5. No minification (human-readable code)

Use for: Active development, debugging

Production Build

npm run build

What happens:

  1. TypeScript compiles and checks types (tsc)
  2. Vite bundles all code
  3. Minifies JavaScript and CSS
  4. Optimizes assets (images, fonts)
  5. Generates static files in dist/ folder
  6. Creates optimized chunks for code splitting

Output:

vite v5.0.8 building for production...
✓ 34 modules transformed.
dist/index.html                   0.46 kB │ gzip:  0.30 kB
dist/assets/react-35ef61ed.svg    4.13 kB │ gzip:  2.14 kB
dist/assets/index-d526a0c5.css    1.42 kB │ gzip:  0.74 kB
dist/assets/index-b9e74e72.js   143.42 kB │ gzip: 46.09 kB
✓ built in 857ms

Preview Production Build

npm run preview

Serves production build locally for testing:

  ➜  Local:   http://localhost:4173/
  ➜  Network: use --host to expose

Use for: Testing production build before deployment

TypeScript Configuration Basics

Vite generates TypeScript configuration automatically.

tsconfig.json Overview

{
  "compilerOptions": {
    "target": "ES2020", // JavaScript version to compile to
    "useDefineForClassFields": true,
    "lib": ["ES2020", "DOM", "DOM.Iterable"], // Available APIs
    "module": "ESNext", // Module system
    "skipLibCheck": true, // Speed up compilation
 
    /* Bundler mode */
    "moduleResolution": "bundler",
    "allowImportingTsExtensions": true,
    "resolveJsonModule": true,
    "isolatedModules": true,
    "noEmit": true, // Don't emit JS (Vite handles this)
    "jsx": "react-jsx", // JSX transformation
 
    /* Linting */
    "strict": true, // Enable all strict checks
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "noFallthroughCasesInSwitch": true
  },
  "include": ["src"],
  "references": [{ "path": "./tsconfig.node.json" }]
}

Key settings:

  • strict: Enables strict type checking (recommended)
  • jsx: Configures JSX transformation (react-jsx uses new transform)
  • noEmit: Vite handles compilation, TypeScript only checks types
  • lib: Includes DOM types for browser APIs

Don't edit unless you know what you're doing - defaults work well.

Type Checking

TypeScript checks types during build:

npm run build

If type errors exist, build fails with detailed messages.

Manual type check (without building):

npx tsc --noEmit

Shows type errors without emitting files.

Add Your Second Component

Let's create a reusable component to understand component composition.

Create Greeting Component

Create new file src/Greeting.tsx:

interface GreetingProps {
  name: string
  isExcited?: boolean
}
 
function Greeting({ name, isExcited = false }: GreetingProps) {
  const punctuation = isExcited ? '!' : '.'
 
  return (
    <div>
      <h2>Welcome, {name}{punctuation}</h2>
      <p>This is a reusable Greeting component.</p>
    </div>
  )
}
 
export default Greeting

TypeScript features:

  • Interface: Defines prop types (GreetingProps)
  • Required prop: name: string must be provided
  • Optional prop: isExcited?: boolean has default value
  • Type safety: TypeScript ensures correct usage

Use Greeting Component

Update src/App.tsx to use the new component:

import { useState } from 'react'
import Greeting from './Greeting'
import './App.css'
 
function App() {
  const [name, setName] = useState('World')
 
  return (
    <div className="App">
      <h1>React TypeScript Demo</h1>
 
      <Greeting name={name} isExcited={true} />
 
      <input
        type="text"
        value={name}
        onChange={(e) => setName(e.target.value)}
        placeholder="Enter your name"
      />
    </div>
  )
}
 
export default App

Save and observe:

  • Browser updates instantly via HMR
  • Greeting component displays with exclamation mark
  • Typing in input updates greeting
  • TypeScript ensures you pass correct props

Try this: Remove name={name} from Greeting - TypeScript shows error immediately.

Verify Your Setup Works

Let's confirm everything is functioning correctly.

Test 1: Node.js and npm Installed

node --version
npm --version

Should show Node.js 18+ and npm 9+.

Test 2: Create Project

npm create vite@latest test-react-app -- --template react-ts
cd test-react-app
npm install

Should create project and install dependencies without errors.

Test 3: Start Development Server

npm run dev

Should start server and show local URL.

Test 4: Access Application

Open browser to displayed URL - should see React + Vite welcome page.

Test 5: Production Build

npm run build

Should compile TypeScript and create dist/ folder with optimized files.

Test 6: Preview Production

npm run preview

Should serve production build and show preview URL.

All tests passed? Your React TypeScript setup is complete!

Summary

What you've accomplished:

  • Verified Node.js 18+ and npm installation
  • Understood React setup method options (Vite recommended)
  • Created React application with TypeScript using Vite
  • Explored project structure and key files
  • Wrote your first React component with state management
  • Started development server with Hot Module Replacement
  • Created reusable component with TypeScript props
  • Built production-ready application bundle
  • Previewed production build locally

Key commands learned:

  • npm create vite@latest - Create new Vite project
  • npm install - Install dependencies
  • npm run dev - Start development server
  • npm run build - Build for production
  • npm run preview - Preview production build
  • npx tsc --noEmit - Type-check without building

Skills gained:

  • React project setup with modern tooling
  • Component creation with TypeScript
  • State management with useState hook
  • JSX syntax and reactive rendering
  • Development workflow with HMR
  • Production build optimization
  • TypeScript configuration basics

Next Steps

Ready to learn React fundamentals?

  • Quick Start (5-30% coverage) - Touch all core React concepts in a fast-paced tour

Want comprehensive React mastery?

Prefer code-first learning?

Want to understand React's design philosophy?

  • Overview - Why React exists and when to use it

Troubleshooting Common Issues

"npm: command not found"

Problem: Node.js/npm not installed or not in PATH.

Solution:

  • Install Node.js following platform-specific instructions above
  • Ensure Node.js bin directory in PATH
  • Restart terminal after installation
  • Verify: node --version and npm --version

"EACCES: permission denied" on Linux/macOS

Problem: npm trying to install globally without permissions.

Solution:

  • DO NOT use sudo with npm - creates permission issues
  • Use nvm (Node Version Manager) instead:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | bash
source ~/.bashrc  # or ~/.zshrc
nvm install 18
nvm use 18
  • Or configure npm to use user directory:
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc

"Port 5173 is already in use"

Problem: Another process using port 5173.

Solution:

  • Vite automatically finds next available port
  • Or manually specify port in vite.config.ts:
export default defineConfig({
  plugins: [react()],
  server: {
    port: 3000,
  },
});

TypeScript errors after project creation

Problem: Type declaration issues or outdated types.

Solution:

  • Update TypeScript and type packages:
npm install -D typescript@latest @types/react@latest @types/react-dom@latest
  • Delete node_modules and reinstall:
rm -rf node_modules package-lock.json
npm install

"Cannot find module" errors

Problem: Import path or dependency issues.

Solution:

  • Check import paths match file locations
  • Ensure file extensions correct (.tsx for components, .ts for utilities)
  • Verify dependencies installed: npm install
  • Check package.json has required packages

Development server starts but shows blank page

Problem: JavaScript errors preventing rendering.

Solution:

  • Open browser DevTools (F12) and check Console tab
  • Look for error messages with stack traces
  • Common issues:
    • Syntax errors in JSX
    • Missing imports
    • Incorrect prop types
    • State initialization errors

HMR not working

Problem: Changes not reflecting in browser.

Solution:

  • Hard refresh browser: Ctrl+Shift+R (Windows/Linux) or Cmd+Shift+R (macOS)
  • Restart development server: Ctrl+C then npm run dev
  • Clear browser cache
  • Check browser console for HMR connection errors

Build fails with "Out of memory"

Problem: Large project or insufficient memory.

Solution:

  • Increase Node.js memory limit:
export NODE_OPTIONS="--max-old-space-size=4096"
npm run build
  • Or in package.json:
{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=4096' tsc && vite build"
  }
}

"Cannot access 'X' before initialization"

Problem: Circular dependencies or hoisting issues.

Solution:

  • Reorganize imports to avoid circular dependencies
  • Move component definitions before usage
  • Use dynamic imports for code splitting if needed

Further Resources

Official React Documentation:

TypeScript and React:

Vite:

Interactive Learning:

Community:

Advanced Topics:

Last updated January 28, 2025

Command Palette

Search for a command to run...