React Basics

React is a popular JavaScript library for building user interfaces, especially single-page applications. Developed by Facebook, React allows developers to create large web applications that can update and render efficiently in response to data changes.

Getting Started

To get started with React, you need to install Node.js and npm. Then you can create a new React application using Create React App:

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

// Create a new React application
create-react-app my-app

// Navigate into the application directory
cd my-app

// Start the development server
npm start
            

The development server will start, and you can view your application in the browser at http://localhost:3000.

Components

Components are the building blocks of a React application. A component can be a class or a function that returns a React element:

Class Components

import React, { Component } from 'react';

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

export default Welcome;
            

Function Components

import React from 'react';

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

export default Welcome;
            

Function components are simpler and are recommended for most components, especially with the introduction of Hooks.

State and Props

State and props are two types of data that control a component's behavior and rendering:

Props

Props (short for properties) are read-only attributes passed from parent to child components:

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

// Using the component
<Greeting name="Alice" />
            

State

State is a local data storage that is local to the component and can be changed. State is managed within the component:

import React, { Component } from 'react';

class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
    }

    increment = () => {
        this.setState({ count: this.state.count + 1 });
    };

    render() {
        return (
            <div>
                <p>Count: {this.state.count}</p>
                <button onClick={this.increment}>Increment</button>
            </div>
        );
    }
}

export default Counter;
            

Lifecycle Methods

Lifecycle methods are hooks that allow you to run code at particular times in a component's lifecycle:

Mounting

These methods are called when an instance of a component is being created and inserted into the DOM:

Updating

These methods are called when a component is being re-rendered:

Unmounting

This method is called when a component is being removed from the DOM:

Hooks

Hooks are functions that let you "hook into" React state and lifecycle features from function components. They are a powerful addition introduced in React 16.8:

useState

The useState hook lets you add state to function components:

import React, { useState } from 'react';

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

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

export default Counter;
            

useEffect

The useEffect hook lets you perform side effects in function components:

import React, { useEffect } from 'react';

function Timer() {
    useEffect(() => {
        const interval = setInterval(() => {
            console.log('Tick');
        }, 1000);

        return () => clearInterval(interval);
    }, []);

    return <div>Check the console for ticks.</div>;
}

export default Timer;
            

Other useful hooks include useContext, useReducer, useMemo, and useRef.

React Router

React Router is a standard library for routing in React. It enables navigation among views of various components in a React Application, allows changing the browser URL, and keeps UI in sync with the URL:

import React from 'react';
import { BrowserRouter as Router, Route, Switch, Link } from 'react-router-dom';

function Home() {
    return <h2>Home</h2>;
}

function About() {
    return <h2>About</h2>;
}

function App() {
    return (
        <Router>
            <div>
                <nav>
                    <ul>
                        <li>
                            <Link to="/">Home</Link>
                        </li>
                        <li>
                            <Link to="/about">About</Link>
                        </li>
                    </ul>
                </nav>
                <Switch>
                    <Route path="/about">
                        <About />
                    </Route>
                    <Route path="/">
                        <Home />
                    </Route>
                </Switch>
            </div>
        </Router>
    );
}

export default App;
            

Context API

The Context API provides a way to pass data through the component tree without having to pass props down manually at every level:

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

const MyContext = createContext();

function Parent() {
    return (
        <MyContext.Provider value="Hello from context">
            <Child />
        </MyContext.Provider>
    );
}

function Child() {
    const value = useContext(MyContext);
    return <div>{value}</div>;
}

export default Parent;
            

Advanced React Topics

Advanced topics in React include performance optimization, server-side rendering, and TypeScript integration:

Performance Optimization

Server-Side Rendering (SSR)

SSR can improve the performance and SEO of your application. Frameworks like Next.js provide out-of-the-box support for SSR with React:

import React from 'react';

function HomePage() {
    return <div>Welcome to SSR with Next.js!</div>;
}

export default HomePage;
            

TypeScript Integration

TypeScript adds static typing to JavaScript, which can help catch errors early and improve developer experience. You can create a React project with TypeScript using Create React App:

// Create a new React application with TypeScript
npx create-react-app my-app --template typescript
            

State Management with Redux

Redux is a state management library for JavaScript applications, often used with React to manage complex state. It provides a predictable state container that helps in maintaining the state of your application consistently:

Setting Up Redux

First, install Redux and React-Redux:

npm install redux react-redux

Creating a Store

import { createStore } from 'redux';

// Reducer function
const reducer = (state = { count: 0 }, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { count: state.count + 1 };
        case 'DECREMENT':
            return { count: state.count - 1 };
        default:
            return state;
    }
};

// Create store
const store = createStore(reducer);

Connecting Redux to React

import React from 'react';
import ReactDOM from 'react-dom';
import { Provider, useDispatch, useSelector } from 'react-redux';
import { store } from './store';  // Assuming store.js contains the store setup

function Counter() {
    const count = useSelector(state => state.count);
    const dispatch = useDispatch();

    return (
        <div>
            <p>Count: {count}</p>
            <button onClick={() => dispatch({ type: 'INCREMENT' })}>Increment</button>
            <button onClick={() => dispatch({ type: 'DECREMENT' })}>Decrement</button>
        </div>
    );
}

ReactDOM.render(
    <Provider store={store}>
        <Counter />
    </Provider>,
    document.getElementById('root')
);

Testing React Applications

Testing is crucial for maintaining code quality and preventing bugs. React applications can be tested using various tools:

Jest

Jest is a testing framework by Facebook that works well with React. It includes a test runner, assertion library, and mocking support:

npm install --save-dev jest

Create a simple test for a React component:

import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Counter from './Counter';

test('renders counter component', () => {
    render(<Counter />);
    expect(screen.getByText('Count: 0')).toBeInTheDocument();
});

React Testing Library

React Testing Library is a popular library for testing React components:

npm install --save-dev @testing-library/react

Using React Testing Library with Jest:

import { render, screen, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('increments counter', () => {
    render(<Counter />);
    fireEvent.click(screen.getByText('Increment'));
    expect(screen.getByText('Count: 1')).toBeInTheDocument();
});

Integrating with Backend Services

React applications often need to interact with backend services for data fetching, authentication, and other purposes:

Fetching Data with Fetch API

Use the Fetch API to make HTTP requests:

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

function DataFetchingComponent() {
    const [data, setData] = useState([]);

    useEffect(() => {
        fetch('https://api.example.com/data')
            .then(response => response.json())
            .then(data => setData(data));
    }, []);

    return (
        <ul>
            {data.map(item => (
                <li key={item.id}>{item.name}</li>
            ))}
        </ul>
    );
}

export default DataFetchingComponent;

Using Axios

Axios is a popular library for making HTTP requests:

npm install axios
import React, { useEffect, useState } from 'react';
import axios from 'axios';

function DataFetchingComponent() {
    const [data, setData] = useState([]);

    useEffect(() => {
        axios.get('https://api.example.com/data')
            .then(response => setData(response.data));
    }, []);

    return (
        <ul>
            {data.map(item => (
                <li key={item.id}>{item.name}</li>
            ))}
        </ul>
    );
}

export default DataFetchingComponent;

Handling Forms in React

Forms are a common feature in web applications. Handling forms in React involves managing state and form submissions:

Controlled Components

In controlled components, form data is handled by the React component's state:

import React, { useState } from 'react';

function FormComponent() {
    const [name, setName] = useState('');

    const handleSubmit = (event) => {
        event.preventDefault();
        alert(`Form submitted with name: ${name}`);
    };

    return (
        <form onSubmit={handleSubmit}>
            <label>
                Name:
                <input type="text" value={name} onChange={(e) => setName(e.target.value)} />
            </label>
            <button type="submit">Submit</button>
        </form>
    );
}

export default FormComponent;

Formik

Formik is a popular library for managing form state and validation in React:

npm install formik
import React from 'react';
import { Formik, Field, Form } from 'formik';

function FormikForm() {
    return (
        <Formik
            initialValues={{ name: '' }}
            onSubmit={(values) => {
                alert(`Form submitted with name: ${values.name}`);
            }}
        >
            <Form>
                <label>
                    Name:
                    <Field name="name" type="text" />
                </label>
                <button type="submit">Submit</button>
            </Form>
        </Formik>
    );
}

export default FormikForm;