Skip to content

React Basics

A comprehensive guide to React fundamentals for beginners and intermediate developers.

Introduction to React

React is a JavaScript library for building user interfaces, particularly single-page applications. It's used for handling the view layer in web and mobile apps. React allows you to design simple views for each state in your application, and it will efficiently update and render just the right components when your data changes.

Key Features of React

  • Component-Based Architecture: Build encapsulated components that manage their own state
  • Declarative UI: Design simple views for each state in your application
  • Virtual DOM: Efficiently update and render components when data changes
  • JSX: JavaScript syntax extension that allows HTML-like code in JavaScript
  • Unidirectional Data Flow: Data flows down from parent to child components

Getting Started with React

Prerequisites

Before starting with React, you should have:

  • Basic knowledge of HTML, CSS, and JavaScript
  • Understanding of ES6 features (arrow functions, classes, destructuring, etc.)
  • Node.js and npm installed on your system

Setting Up a React Project

bash
# Install Create React App globally
npm install -g create-react-app

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

# Navigate to project directory
cd my-react-app

# Start the development server
npm start

Using Vite (Faster Alternative)

bash
# Create a new React project with Vite
npm create vite@latest my-react-app -- --template react

# Navigate to project directory
cd my-react-app

# Install dependencies
npm install

# Start the development server
npm run dev

Core Concepts

1. Components

Components are the building blocks of React applications. They are reusable pieces of code that return React elements describing what should appear on the screen.

Functional Components

jsx
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

// Using arrow function syntax
const Welcome = (props) => {
  return <h1>Hello, {props.name}</h1>;
};

Class Components

jsx
import React, { Component } from 'react';

class Welcome extends Component {
  render() {
    return <h1>Hello, {this.props.name}</h1>;
  }
}

2. JSX

JSX is a syntax extension for JavaScript that looks similar to HTML. It makes React code more readable and expressive.

jsx
const element = <h1>Hello, world!</h1>;

// JSX with expressions
const name = 'John';
const element = <h1>Hello, {name}!</h1>;

// JSX with attributes
const element = <img src={user.avatarUrl} alt={user.name} />;

// JSX with children
const element = (
  <div>
    <h1>Hello!</h1>
    <p>Good to see you here.</p>
  </div>
);

3. Props

Props (short for properties) are read-only inputs to components. They allow you to pass data from a parent component to a child component.

jsx
// Parent component
function App() {
  return <Welcome name="Sara" />;
}

// Child component
function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

4. State

State is a JavaScript object that stores component data that may change over time. When state changes, the component re-renders.

jsx
import React, { useState } from 'react';

function Counter() {
  // Declare a state variable named "count" with initial value 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

5. Lifecycle and Effects

In functional components, the useEffect hook lets you perform side effects (like data fetching, subscriptions, or DOM manipulation).

jsx
import React, { useState, useEffect } from 'react';

function Example() {
  const [count, setCount] = useState(0);

  // Similar to componentDidMount and componentDidUpdate
  useEffect(() => {
    // Update the document title using the browser API
    document.title = `You clicked ${count} times`;
    
    // Optional cleanup function (similar to componentWillUnmount)
    return () => {
      document.title = 'React App';
    };
  }, [count]); // Only re-run the effect if count changes

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={() => setCount(count + 1)}>
        Click me
      </button>
    </div>
  );
}

Handling Events

React events are named using camelCase and passed as functions rather than strings.

jsx
function ActionButton() {
  function handleClick(e) {
    e.preventDefault();
    console.log('The button was clicked');
  }

  return (
    <button onClick={handleClick}>
      Click me
    </button>
  );
}

Conditional Rendering

You can use JavaScript operators like if or the conditional (ternary) operator to create elements representing the current state.

jsx
function UserGreeting(props) {
  return <h1>Welcome back!</h1>;
}

function GuestGreeting(props) {
  return <h1>Please sign up.</h1>;
}

function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  
  if (isLoggedIn) {
    return <UserGreeting />;
  }
  return <GuestGreeting />;
}

// Using ternary operator
function Greeting(props) {
  const isLoggedIn = props.isLoggedIn;
  
  return (
    <>
      {isLoggedIn ? <UserGreeting /> : <GuestGreeting />}
    </>
  );
}

Lists and Keys

React uses keys to identify which items have changed, are added, or are removed in a list.

jsx
function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    <li key={number.toString()}>
      {number}
    </li>
  );
  
  return (
    <ul>{listItems}</ul>
  );
}

Forms

In React, form elements naturally keep some internal state. To have controlled components, you need to manage the form data with React state.

jsx
import React, { useState } from 'react';

function NameForm() {
  const [value, setValue] = useState('');

  const handleChange = (event) => {
    setValue(event.target.value);
  };

  const handleSubmit = (event) => {
    alert('A name was submitted: ' + value);
    event.preventDefault();
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        Name:
        <input type="text" value={value} onChange={handleChange} />
      </label>
      <input type="submit" value="Submit" />
    </form>
  );
}

Best Practices

Component Organization

  • Keep components small and focused on a single responsibility
  • Use a consistent file structure (e.g., one component per file)
  • Group related components in folders

Performance Optimization

  • Use React.memo for functional components that render often with the same props
  • Use the useCallback hook to memoize functions
  • Use the useMemo hook to memoize expensive calculations
  • Use the React DevTools Profiler to identify performance bottlenecks
jsx
import React, { memo, useCallback, useMemo } from 'react';

const ExpensiveComponent = memo(function ExpensiveComponent({ data, onItemClick }) {
  // This component will only re-render if data or onItemClick changes
  return (
    <div>
      {data.map(item => (
        <div key={item.id} onClick={() => onItemClick(item.id)}>
          {item.name}
        </div>
      ))}
    </div>
  );
});

function ParentComponent() {
  const [items, setItems] = useState([/* some data */]);
  
  // useCallback memoizes the function
  const handleItemClick = useCallback((id) => {
    console.log('Item clicked:', id);
  }, []);
  
  // useMemo memoizes the computed value
  const sortedItems = useMemo(() => {
    return [...items].sort((a, b) => a.name.localeCompare(b.name));
  }, [items]);
  
  return (
    <ExpensiveComponent 
      data={sortedItems} 
      onItemClick={handleItemClick} 
    />
  );
}

Code Style and Conventions

  • Use functional components with hooks instead of class components
  • Use destructuring for props and state
  • Use the spread operator for copying objects and arrays
  • Follow the ESLint rules recommended by Create React App

Common Patterns

Context API for State Management

For sharing state across many components without prop drilling:

jsx
import React, { createContext, useContext, useState } from 'react';

// Create a context
const ThemeContext = createContext();

// Provider component
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prevTheme => prevTheme === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Consumer component
function ThemedButton() {
  const { theme, toggleTheme } = useContext(ThemeContext);
  
  return (
    <button 
      onClick={toggleTheme}
      style={{ 
        background: theme === 'light' ? '#fff' : '#333',
        color: theme === 'light' ? '#333' : '#fff'
      }}
    >
      Toggle Theme
    </button>
  );
}

// App
function App() {
  return (
    <ThemeProvider>
      <div>
        <h1>Theme Example</h1>
        <ThemedButton />
      </div>
    </ThemeProvider>
  );
}

Custom Hooks

Extract reusable logic into custom hooks:

jsx
import { useState, useEffect } from 'react';

// Custom hook for fetching data
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchData = async () => {
      try {
        setLoading(true);
        const response = await fetch(url);
        
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
        
        const result = await response.json();
        setData(result);
        setError(null);
      } catch (error) {
        setError(error.message);
        setData(null);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [url]);

  return { data, loading, error };
}

// Using the custom hook
function UserProfile({ userId }) {
  const { data, loading, error } = useFetch(`https://api.example.com/users/${userId}`);

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;
  
  return (
    <div>
      <h1>{data.name}</h1>
      <p>Email: {data.email}</p>
    </div>
  );
}

Frequently Asked Questions

What's the difference between state and props?

  • Props are passed to a component from its parent and are read-only
  • State is managed within the component and can be updated using setState or useState

When should I use class components vs. functional components?

In modern React (16.8+), functional components with hooks are preferred for most use cases. Class components are still supported but mainly used for legacy code or specific use cases.

How do I handle forms in React?

Use controlled components where form data is handled by React state, or use libraries like Formik or React Hook Form for complex forms.

How do I style React components?

Several approaches:

  • Regular CSS with className
  • Inline styles with the style attribute
  • CSS Modules
  • CSS-in-JS libraries (styled-components, emotion)
  • Utility-first CSS frameworks (Tailwind CSS)

How do I optimize performance in React?

  • Use React.memo for functional components
  • Use useCallback and useMemo hooks
  • Implement virtualization for long lists
  • Use code splitting with React.lazy and Suspense
  • Avoid unnecessary re-renders

This document will be continuously updated. If you have any questions, please provide feedback through GitHub Issues.

VitePress Development Guide