DEV Community

Vikash Kumar
Vikash Kumar

Posted on • Originally published at Medium on

React 101: Quick Start Guide

What is React?

React is a JavaScript library for building user interfaces, developed by Facebook. It allows you to create reusable UI components and efficiently update the DOM when data changes.

Key Features:

  • Component-Based : Build encapsulated components that manage their own state
  • Declarative : Design simple views for each state, React efficiently updates and renders components
  • Learn Once, Write Anywhere : Create web apps, mobile apps (React Native), and more

Setup & Installation

# Create a new React app
npx create-react-app my-app

# Navigate to the project
cd my-app
# Start development server
npm start
Enter fullscreen mode Exit fullscreen mode

Project Structure:

my-app/
├── node_modules/
├── public/
│ └── index.html
├── src/
│ ├── App.js # Main component
│ ├── App.css # Styles
│ ├── index.js # Entry point
│ └── index.css
└── package.json
Enter fullscreen mode Exit fullscreen mode

JSX Syntax

JSX (JavaScript XML) allows you to write HTML-like code in JavaScript.

// JSX Example
const element = <h1>Hello, World!</h1>;

---

// JSX with expressions
const name = "John";
const greeting = <h1>Hello, {name}!</h1>;
// JSX with attributes
const image = <img src="photo.jpg" alt="Profile" />;
// JSX with multiple elements (must have one parent)
const card = (
  <div className="card">
    <h2>Title</h2>
    <p>Description</p>
  </div>
);
// JSX Rules:
// - Use className instead of class
// - Use camelCase for attributes (onClick, onChange)
// - Close all tags (<img />, <input />)
// - Use {} for JavaScript expressions
Enter fullscreen mode Exit fullscreen mode

Components

Components are the building blocks of React applications. They come in two types: Functional and Class components (modern React favors functional components).

Functional Component

// Simple functional component
function Welcome() {
  return <h1>Welcome to React!</h1>;
}

// Arrow function component
const Greeting = () => {
  return <h1>Hello!</h1>;
};
// Component with JavaScript logic
function UserCard() {
  const user = {
    name: "Alice",
    age: 25
  };
  return (
    <div>
      <h2>{user.name}</h2>
      <p>Age: {user.age}</p>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Class Component (Legacy)

import React, { Component } from 'react';

class Welcome extends Component {
  render() {
    return <h1>Welcome to React!</h1>;
  }
}
Enter fullscreen mode Exit fullscreen mode

Props

Props (properties) allow you to pass data from parent to child components. They are read-only.

// Parent component passing props
function App() {
  return (
    <div>
      <Greeting name="Alice" age={25} />
      <Greeting name="Bob" age={30} />
    </div>
  );
}

// Child component receiving props
function Greeting(props) {
  return (
    <div>
      <h2>Hello, {props.name}!</h2>
      <p>Age: {props.age}</p>
    </div>
  );
}
// Using destructuring (cleaner)
function Greeting({ name, age }) {
  return (
    <div>
      <h2>Hello, {name}!</h2>
      <p>Age: {age}</p>
    </div>
  );
}
// Default props
function Greeting({ name = "Guest", age = 0 }) {
  return <h2>Hello, {name}! Age: {age}</h2>;
}
// Props children
function Card({ children }) {
  return <div className="card">{children}</div>;
}
// Usage
<Card>
  <h2>Title</h2>
  <p>Content here</p>
</Card>
Enter fullscreen mode Exit fullscreen mode

State

State is data that changes over time within a component. Use the useState hook to manage state in functional components.

import { useState } from 'react';

function Counter() {
  // Declare state variable
  const [count, setCount] = useState(0);
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
      <button onClick={() => setCount(count - 1)}>Decrement</button>
      <button onClick={() => setCount(0)}>Reset</button>
    </div>
  );
}
// Multiple state variables
function UserForm() {
  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [age, setAge] = useState(0);
  return (
    <div>
      <input 
        value={name} 
        onChange={(e) => setName(e.target.value)} 
        placeholder="Name"
      />
      <input 
        value={email} 
        onChange={(e) => setEmail(e.target.value)} 
        placeholder="Email"
      />
      <input 
        type="number"
        value={age} 
        onChange={(e) => setAge(e.target.value)} 
        placeholder="Age"
      />
    </div>
  );
}
// State with objects
function UserProfile() {
  const [user, setUser] = useState({
    name: 'Alice',
    age: 25,
    email: 'alice@example.com'
  });
  const updateName = (newName) => {
    setUser({ ...user, name: newName }); // Spread operator to maintain other properties
  };
  return (
    <div>
      <h2>{user.name}</h2>
      <button onClick={() => updateName('Bob')}>Change Name</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Event Handling

React events are named using camelCase and pass functions as handlers.

function EventExamples() {
  // Click event
  const handleClick = () => {
    alert('Button clicked!');
  };

 // Event with parameter
  const greet = (name) => {
    alert(`Hello, ${name}!`);
  };
  // Form submission
  const handleSubmit = (e) => {
    e.preventDefault(); // Prevent page reload
    console.log('Form submitted');
  };
  // Input change
  const handleChange = (e) => {
    console.log('Input value:', e.target.value);
  };
  // Mouse events
  const handleMouseEnter = () => {
    console.log('Mouse entered!');
  };
  return (
    <div>
      <button onClick={handleClick}>Click Me</button>
      <button onClick={() => greet('Alice')}>Greet Alice</button>

      <form onSubmit={handleSubmit}>
        <input onChange={handleChange} />
        <button type="submit">Submit</button>
      </form>
      <div 
        onMouseEnter={handleMouseEnter}
        onMouseLeave={() => console.log('Mouse left!')}
      >
        Hover over me
      </div>
    </div>
  );
}
// Common Events:
// onClick, onChange, onSubmit, onFocus, onBlur
// onMouseEnter, onMouseLeave, onKeyDown, onKeyUp
Enter fullscreen mode Exit fullscreen mode

Conditional Rendering

Render components based on conditions using JavaScript operators.

function LoginStatus({ isLoggedIn }) {
  // Using if-else
  if (isLoggedIn) {
    return <h1>Welcome back!</h1>;
  } else {
    return <h1>Please sign in</h1>;
  }
}

// Using ternary operator
function Greeting({ isLoggedIn }) {
  return (
    <div>
      {isLoggedIn ? <h1>Welcome!</h1> : <h1>Please log in</h1>}
    </div>
  );
}
// Using && operator (for single condition)
function Notification({ hasMessages }) {
  return (
    <div>
      <h1>Dashboard</h1>
      {hasMessages && <p>You have new messages!</p>}
    </div>
  );
}
// Conditional rendering with multiple conditions
function UserPanel({ user, isAdmin }) {
  return (
    <div>
      {user ? (
        <div>
          <h2>{user.name}</h2>
          {isAdmin && <button>Admin Panel</button>}
        </div>
      ) : (
        <button>Login</button>
      )}
    </div>
  );
}
// Switch-case alternative
function StatusMessage({ status }) {
  const getMessage = () => {
    switch(status) {
      case 'loading': return 'Loading...';
      case 'success': return 'Success!';
      case 'error': return 'Error occurred';
      default: return 'Unknown status';
    }
  };
  return <p>{getMessage()}</p>;
}
Enter fullscreen mode Exit fullscreen mode

Lists & Keys

Render arrays of data using map() and assign unique keys to list items.

function TodoList() {
  const todos = [
    { id: 1, text: 'Learn React', completed: false },
    { id: 2, text: 'Build a project', completed: false },
    { id: 3, text: 'Deploy app', completed: true }
  ];

return (
    <ul>
      {todos.map((todo) => (
        <li key={todo.id}>
          {todo.text} {todo.completed && '✓'}
        </li>
      ))}
    </ul>
  );
}
// Keys help React identify which items have changed
// Use unique IDs, not array indexes (when possible)
// More complex example
function UserList() {
  const users = [
    { id: 1, name: 'Alice', role: 'Admin' },
    { id: 2, name: 'Bob', role: 'User' },
    { id: 3, name: 'Charlie', role: 'User' }
  ];
  return (
    <div>
      {users.map((user) => (
        <div key={user.id} className="user-card">
          <h3>{user.name}</h3>
          <span>{user.role}</span>
        </div>
      ))}
    </div>
  );
}
// Filtering lists
function ProductList() {
  const products = [
    { id: 1, name: 'Laptop', price: 999, inStock: true },
    { id: 2, name: 'Phone', price: 699, inStock: false },
    { id: 3, name: 'Tablet', price: 499, inStock: true }
  ];
  return (
    <div>
      <h2>Available Products</h2>
      {products
        .filter(product => product.inStock)
        .map(product => (
          <div key={product.id}>
            <h3>{product.name}</h3>
            <p>${product.price}</p>
          </div>
        ))}
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

Hooks Overview

Hooks let you use state and other React features in functional components.

Common Hooks:

  • useState : Manage state
  • useEffect : Side effects (API calls, subscriptions)
  • useContext : Access context values
  • useRef : Access DOM elements or persist values
  • useMemo : Memoize expensive calculations
  • useCallback : Memoize functions
import { useState, useEffect, useRef, useMemo } from 'react';

// useState - covered in State section
const [count, setCount] = useState(0);
// useRef - Access DOM elements
function TextInput() {
  const inputRef = useRef(null);
  const focusInput = () => {
    inputRef.current.focus();
  };
  return (
    <div>
      <input ref={inputRef} />
      <button onClick={focusInput}>Focus Input</button>
    </div>
  );
}
// useMemo - Optimize performance
function ExpensiveComponent({ numbers }) {
  const sum = useMemo(() => {
    console.log('Calculating sum...');
    return numbers.reduce((a, b) => a + b, 0);
  }, [numbers]); // Only recalculate when numbers change
  return <div>Sum: {sum}</div>;
}
Enter fullscreen mode Exit fullscreen mode

useEffect Hook

useEffect handles side effects like data fetching, subscriptions, and DOM manipulation.

import { useState, useEffect } from 'react';

// Run on every render
function Example1() {
  useEffect(() => {
    console.log('Component rendered');
  });
}
// Run once on mount (empty dependency array)
function Example2() {
  useEffect(() => {
    console.log('Component mounted');
  }, []);
}
// Run when specific values change
function Example3() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    console.log('Count changed:', count);
  }, [count]); // Only runs when count changes
}
// Cleanup function
function Example4() {
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Tick');
    }, 1000);
    // Cleanup when component unmounts
    return () => {
      clearInterval(timer);
    };
  }, []);
}
// Practical example: Fetch data from API
function UserProfile({ userId }) {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  useEffect(() => {
    setLoading(true);

    fetch(`https://api.example.com/users/${userId}`)
      .then(response => response.json())
      .then(data => {
        setUser(data);
        setLoading(false);
      })
      .catch(err => {
        setError(err.message);
        setLoading(false);
      });
  }, [userId]); // Re-fetch when userId changes
  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  if (!user) return <div>No user found</div>;
  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
    </div>
  );
}
// Document title update
function PageTitle() {
  const [count, setCount] = useState(0);
  useEffect(() => {
    document.title = `Count: ${count}`;
  }, [count]);
  return (
    <button onClick={() => setCount(count + 1)}>
      Clicked {count} times
    </button>
  );
}
Enter fullscreen mode Exit fullscreen mode

Forms & Controlled Components

In React, form elements are controlled by component state.

import { useState } from 'react';

// Simple form
function LoginForm() {
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Login:', { username, password });
    // API call here
  };
  return (
    <form onSubmit={handleSubmit}>
      <input
        type="text"
        value={username}
        onChange={(e) => setUsername(e.target.value)}
        placeholder="Username"
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
      />
      <button type="submit">Login</button>
    </form>
  );
}
// Complex form with validation
function RegistrationForm() {
  const [formData, setFormData] = useState({
    name: '',
    email: '',
    age: '',
    country: 'USA',
    subscribe: false
  });
  const [errors, setErrors] = useState({});
  const handleChange = (e) => {
    const { name, value, type, checked } = e.target;
    setFormData({
      ...formData,
      [name]: type === 'checkbox' ? checked : value
    });
  };
  const validate = () => {
    const newErrors = {};

    if (!formData.name) newErrors.name = 'Name is required';
    if (!formData.email) newErrors.email = 'Email is required';
    if (formData.age < 18) newErrors.age = 'Must be 18 or older';

    return newErrors;
  };
  const handleSubmit = (e) => {
    e.preventDefault();
    const newErrors = validate();

    if (Object.keys(newErrors).length === 0) {
      console.log('Form submitted:', formData);
      // Submit to API
    } else {
      setErrors(newErrors);
    }
  };
  return (
    <form onSubmit={handleSubmit}>
      <div>
        <input
          name="name"
          value={formData.name}
          onChange={handleChange}
          placeholder="Name"
        />
        {errors.name && <span className="error">{errors.name}</span>}
      </div>
      <div>
        <input
          name="email"
          type="email"
          value={formData.email}
          onChange={handleChange}
          placeholder="Email"
        />
        {errors.email && <span className="error">{errors.email}</span>}
      </div>
      <div>
        <input
          name="age"
          type="number"
          value={formData.age}
          onChange={handleChange}
          placeholder="Age"
        />
        {errors.age && <span className="error">{errors.age}</span>}
      </div>
      <div>
        <select name="country" value={formData.country} onChange={handleChange}>
          <option value="USA">USA</option>
          <option value="UK">UK</option>
          <option value="Canada">Canada</option>
        </select>
      </div>
      <div>
        <label>
          <input
            name="subscribe"
            type="checkbox"
            checked={formData.subscribe}
            onChange={handleChange}
          />
          Subscribe to newsletter
        </label>
      </div>
      <button type="submit">Register</button>
    </form>
  );
}
// Textarea example
function CommentForm() {
  const [comment, setComment] = useState('');
  return (
    <form>
      <textarea
        value={comment}
        onChange={(e) => setComment(e.target.value)}
        placeholder="Write a comment..."
        rows="4"
      />
      <p>Character count: {comment.length}</p>
    </form>
  );
}
Enter fullscreen mode Exit fullscreen mode

Component Lifecycle

Understanding when components mount, update, and unmount.

import { useState, useEffect } from 'react';

function LifecycleDemo() {
  const [count, setCount] = useState(0);
  // 1. Component Mounts (runs once)
  useEffect(() => {
    console.log('Component mounted');

    // Cleanup when component unmounts
    return () => {
      console.log('Component will unmount');
    };
  }, []);
  // 2. Component Updates (runs when count changes)
  useEffect(() => {
    console.log('Count updated:', count);
  }, [count]);
  // 3. Every render
  useEffect(() => {
    console.log('Component rendered');
  });
  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
// Lifecycle phases:
// 1. Mounting: Component is created and inserted into the DOM
// 2. Updating: Component re-renders due to state/props changes
// 3. Unmounting: Component is removed from the DOM
Enter fullscreen mode Exit fullscreen mode

Quick Reference

Component Structure

import { useState, useEffect } from 'react';

function MyComponent({ prop1, prop2 }) {
  // 1. Hooks (at the top)
  const [state, setState] = useState(initialValue);

  useEffect(() => {
    // Side effects
  }, [dependencies]);
  // 2. Event handlers
  const handleClick = () => {
    // Handle event
  };
  // 3. Helper functions
  const calculateSomething = () => {
    // Logic
  };
  // 4. Return JSX
  return (
    <div>
      <h1>{prop1}</h1>
      <button onClick={handleClick}>Click</button>
    </div>
  );
}
export default MyComponent;
Enter fullscreen mode Exit fullscreen mode

Common Patterns

1. Toggle State

const [isOpen, setIsOpen] = useState(false);
const toggle = () => setIsOpen(!isOpen);
Enter fullscreen mode Exit fullscreen mode

2. Update Object State

const [user, setUser] = useState({ name: '', age: 0 });
setUser({ ...user, name: 'Alice' });
Enter fullscreen mode Exit fullscreen mode

3. Update Array State

const [items, setItems] = useState([]);
setItems([...items, newItem]); // Add
setItems(items.filter(item => item.id !== id)); // Remove
Enter fullscreen mode Exit fullscreen mode

4. Conditional Class

<div className={isActive ? 'active' : 'inactive'}>Content</div>
Enter fullscreen mode Exit fullscreen mode

5. Inline Styles

<div style={{ color: 'red', fontSize: '20px' }}>Text</div>
Enter fullscreen mode Exit fullscreen mode

Best Practices

  1. Component Names : Use PascalCase (MyComponent)
  2. Props Naming : Use camelCase (onClick, userName)
  3. State Updates : Never mutate state directly, use setter functions
  4. Keys in Lists : Use unique IDs, not array indexes (when possible)
  5. Event Handlers : Use arrow functions or bind methods
  6. Component Size : Keep components small and focused
  7. File Organization : One component per file
  8. Prop Types : Use TypeScript or PropTypes for type checking

Useful Snippets

Loading State

const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
Enter fullscreen mode Exit fullscreen mode

Modal Toggle

const [showModal, setShowModal] = useState(false);
const openModal = () => setShowModal(true);
const closeModal = () => setShowModal(false);
Enter fullscreen mode Exit fullscreen mode

Form Input Handler

const handleChange = (e) => {
  const { name, value } = e.target;
  setFormData({ ...formData, [name]: value });
};
Enter fullscreen mode Exit fullscreen mode

Complete Mini-App Example

Here’s a complete todo app demonstrating multiple concepts:

import { useState } from 'react';

function TodoApp() {
  const [todos, setTodos] = useState([]);
  const [input, setInput] = useState('');
  const [filter, setFilter] = useState('all'); // all, active, completed
  // Add todo
  const addTodo = (e) => {
    e.preventDefault();
    if (input.trim()) {
      setTodos([
        ...todos,
        { id: Date.now(), text: input, completed: false }
      ]);
      setInput('');
    }
  };
  // Toggle todo completion
  const toggleTodo = (id) => {
    setTodos(
      todos.map(todo =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      )
    );
  };
  // Delete todo
  const deleteTodo = (id) => {
    setTodos(todos.filter(todo => todo.id !== id));
  };
  // Filter todos
  const getFilteredTodos = () => {
    switch(filter) {
      case 'active':
        return todos.filter(todo => !todo.completed);
      case 'completed':
        return todos.filter(todo => todo.completed);
      default:
        return todos;
    }
  };
  const filteredTodos = getFilteredTodos();
  const activeCount = todos.filter(t => !t.completed).length;
  return (
    <div className="todo-app">
      <h1>Todo List</h1>
      {/* Add Todo Form */}
      <form onSubmit={addTodo}>
        <input
          type="text"
          value={input}
          onChange={(e) => setInput(e.target.value)}
          placeholder="What needs to be done?"
        />
        <button type="submit">Add</button>
      </form>
      {/* Filter Buttons */}
      <div className="filters">
        <button 
          onClick={() => setFilter('all')}
          className={filter === 'all' ? 'active' : ''}
        >
          All
        </button>
        <button 
          onClick={() => setFilter('active')}
          className={filter === 'active' ? 'active' : ''}
        >
          Active
        </button>
        <button 
          onClick={() => setFilter('completed')}
          className={filter === 'completed' ? 'active' : ''}
        >
          Completed
        </button>
      </div>
      {/* Todo List */}
      <ul className="todo-list">
        {filteredTodos.length === 0 ? (
          <li className="empty">No todos to display</li>
        ) : (
          filteredTodos.map(todo => (
            <li key={todo.id} className={todo.completed ? 'completed' : ''}>
              <input
                type="checkbox"
                checked={todo.completed}
                onChange={() => toggleTodo(todo.id)}
              />
              <span>{todo.text}</span>
              <button onClick={() => deleteTodo(todo.id)}>Delete</button>
            </li>
          ))
        )}
      </ul>
      {/* Footer */}
      <div className="footer">
        <span>{activeCount} items left</span>
      </div>
    </div>
  );
}
export default TodoApp;
Enter fullscreen mode Exit fullscreen mode

Next Steps

After mastering these basics:

  1. React Router  — Navigation and routing
  2. Context API  — Global state management
  3. Redux/Zustand  — Advanced state management
  4. Custom Hooks  — Reusable logic
  5. Performance Optimization  — memo, useMemo, useCallback
  6. TypeScript  — Type safety
  7. Testing  — Jest and React Testing Library
  8. API Integration  — Axios, Fetch API, React Query
  9. Styling  — CSS Modules, Styled Components, Tailwind
  10. Build Tools  — Vite, Webpack

Resources:

Happy Coding! 🚀

Last Updated: January 17, 2026

Top comments (0)