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:
constructor
componentDidMount
Updating
These methods are called when a component is being re-rendered:
shouldComponentUpdate
componentDidUpdate
Unmounting
This method is called when a component is being removed from the DOM:
componentWillUnmount
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
- Use
React.memo
to prevent unnecessary re-renders. - Use the
useMemo
anduseCallback
hooks to memoize expensive calculations and functions. - Implement code-splitting and lazy loading with
React.lazy
andSuspense
.
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;