React FullStack
React FullStack
js
React.js is a popular JavaScript library used for building interactive user interfaces, especially for
single-page applications. Developed by Facebook, it follows a component-based architecture that
makes UI development more efficient and maintainable. React allows developers to create
reusable UI components and efficiently update and render only the necessary parts of a web
page, leading to better performance.
1. Component-Based Architecture
React applications are built using reusable components, making the code more modular
and maintainable. Each component represents a part of the UI and can have its own logic
and state.
2. Virtual DOM
React uses a Virtual DOM to improve performance. Instead of directly manipulating the
actual DOM, it updates a lightweight copy (Virtual DOM), compares changes, and
updates only the affected elements.
3. JSX (JavaScript XML)
JSX is a syntax extension for JavaScript that allows developers to write HTML-like code
inside JavaScript. It makes the UI code more readable and easier to write.
4. State and Props
o State: A component’s internal data storage, allowing it to manage dynamic
content.
o Props: Short for properties, props allow data to be passed between
components, making them reusable and dynamic.
5. One-Way Data Binding
React follows a unidirectional data flow, ensuring better control over data and making
debugging easier.
6. Hooks
React Hooks (like useState, useEffect) allow functional components to manage state
and side effects without needing class components.
7. React Router
For navigation, React Router enables seamless client-side routing, allowing users to
switch between different views without reloading the page.
8. Strong Community Support
React has a vast ecosystem with numerous third-party libraries, tools, and strong
community support, making it easier for developers to build scalable applications.
function Greeting() {
return <h1>Hello, Welcome to React!</h1>;
}
export default Greeting;
Conclusion
React.js is widely used for building modern web applications due to its efficiency, reusability,
and scalability. With features like the Virtual DOM, component-based structure, and hooks, it
simplifies UI development. Whether you are a beginner or an experienced developer, learning
React can be a valuable skill for front-end development.
Setting up a React.js project is straightforward, and there are multiple ways to get started. Below
is a step-by-step guide to setting up a React environment, along with useful resources for
learning React.
1. Setting Up React.js
Method 1: Using Create React App (CRA) [Recommended for Beginners]
Create React App (CRA) is the easiest way to set up a new React project with a good default
configuration.
Steps to Install:
Vite is a modern build tool that provides a faster and lighter development experience.
Steps to Install:
If you want to use React without setting up a full project, you can use a CDN.
Example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>React with CDN</title>
</head>
<body>
<div id="root"></div>
<script
src="https://unpkg.com/react@18/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@18/umd/react-
dom.development.js"></script>
<script>
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(React.createElement('h1', {}, 'Hello, React!'));
</script>
</body>
</html>
Online Courses
• Scrimba: https://scrimba.com/learn/learnreact
• Codecademy React Course: https://www.codecademy.com/learn/react-101
Books
Conclusion
Setting up React is simple, and there are multiple ways to get started depending on your needs.
Create React App and Vite are the best options for beginners, while CDN is good for quick
testing. With plenty of online resources, documentation, and community support, learning React
has never been easier.
React applications are built using components, which are reusable and independent pieces of UI.
Components use JSX (JavaScript XML) to describe the UI structure in a syntax that resembles
HTML. JSX makes it easier to write and visualize component structures within JavaScript.
1. React Components
A component in React is a JavaScript function or class that returns JSX to render UI elements.
React supports two types of components:
a) Functional Components (Recommended)
Functional components are simpler and primarily use React Hooks for state and lifecycle
management.
function Greeting() {
return <h1>Hello, Welcome to React!</h1>;
}
Class components were used before React Hooks. They include a render() method to return
JSX.
JSX is a syntax extension that allows writing HTML-like code inside JavaScript. React uses JSX
to create UI components more efficiently. JSX elements must follow JavaScript rules, such as
using curly braces {} for expressions.
a) Writing JSX
function App() {
const userName = "John";
return <h1>Hello, {userName}!</h1>;
}
export default App;
b) JSX Rules
• JSX elements must have a single parent element (wrap multiple elements in a
<div> or <> fragment).
• Class attributes in JSX should be written as className (not class).
• Inline styles should use an object with camelCase properties.
function App() {
return (
<div>
<h1 className="heading">Hello, React!</h1>
<p style={{ color: "blue", fontSize: "20px" }}>This is a paragraph.</p>
</div>
);
}
function App() {
return (
<div>
<Greeting />
<p>This is a React app with multiple components.</p>
</div>
);
}
Here, Greeting is a separate component, imported and used inside the App component.
Conclusion
React components make UI development modular and reusable, while JSX simplifies writing
HTML-like structures inside JavaScript. Functional components are the preferred approach due
to their simplicity and compatibility with Hooks. Understanding components and JSX is the
foundation of building React applications.
Functional components are the most commonly used type of component in React. They are
simple JavaScript functions that return JSX (React's syntax for UI rendering). Unlike class
components, functional components are lighter, easier to read, and perform better because
they do not rely on complex lifecycle methods.
function Greeting() {
return <h1>Hello, Welcome to React!</h1>;
}
Props (short for properties) allow passing data from a parent component to a child component.
function App() {
return <Greeting name="John" />;
}
• The Greeting component receives "John" as a prop and displays "Hello, John!"
By default, functional components do not have state. However, React Hooks (like useState)
allow functional components to manage state.
function Counter() {
const [count, setCount] = useState(0); // Declaring state
return (
<div>
<h2>Count: {count}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
The useEffect hook allows functional components to perform side effects like data fetching,
event listeners, or API calls.
function DataFetcher() {
const [data, setData] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/posts")
.then((response) => response.json())
.then((json) => setData(json));
}, []);
return (
<div>
<h2>Posts</h2>
<ul>
{data.slice(0, 5).map((post) => (
<li key={post.id}>{post.title}</li>
))}
</ul>
</div>
);
}
• useEffect(() => {}, []) runs the API call once when the component mounts.
• The component fetches and displays posts dynamically.
Functional components are the foundation of modern React development. They are simple
functions that return JSX and can use Hooks (useState, useEffect) to manage state and side
effects. Due to their efficiency, they have replaced class components in most React applications.
Styling is an essential part of building React applications. React provides multiple ways to apply
CSS styles, from traditional CSS files to modern techniques like CSS modules and styled-
components.
You can create a separate .css file and import it into your React component.
.container {
text-align: center;
background-color: lightblue;
padding: 20px;
border-radius: 10px;
}
• This method works like regular CSS but applies styles globally.
function InlineStyle() {
const headingStyle = {
color: "red",
fontSize: "24px",
textAlign: "center",
backgroundColor: "yellow",
};
CSS Modules allow you to scope styles to a specific component, preventing conflicts.
.title {
color: green;
font-size: 28px;
text-align: center;
}
function App() {
return <h1 className={styles.title}>Styled with CSS Modules</h1>;
}
Styled-components allow defining styles directly inside JavaScript using template literals.
1. Install styled-components:
function App() {
return <Title>Styled with Styled-Components</Title>;
}
Conclusion
React provides multiple ways to style components. External CSS files are simple and widely
used, while inline styles are useful for quick styling. CSS Modules ensure scoped styles, and
styled-components enable modern CSS-in-JS styling. Choosing the right method depends on the
project's needs.
Click events in React are handled using event listeners. React follows the synthetic event system,
meaning events work consistently across different browsers.
React uses the onClick event to detect button clicks. The event is attached to an element using
JSX syntax.
function ClickHandler() {
const handleClick = () => {
alert("Button clicked!");
};
function ClickHandler() {
const showMessage = (name) => {
alert(`Hello, ${name}!`);
};
• The arrow function () => showMessage("John") ensures the function runs only
when clicked.
React components can update state when a button is clicked using the useState hook.
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h2>Count: {count}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
The preventDefault() method prevents the default action of an element, such as stopping a
link from navigating.
function PreventDefault() {
const handleClick = (e) => {
e.preventDefault();
alert("Link click prevented!");
};
Conclusion
Handling click events in React is straightforward using onClick. You can pass parameters,
update state, use event objects, and prevent default behavior. Mastering these techniques is
essential for building interactive React applications.
useState Hook in React
The useState hook is a built-in React hook that allows functional components to manage state.
Unlike class components that use this.state, functional components can use useState to store
and update state values efficiently.
1. What is useState?
function Counter() {
const [count, setCount] = useState(0); // Initial state = 0
return (
<div>
<h2>Count: {count}</h2>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
function Greeting() {
const [name, setName] = useState("Guest");
return (
<div>
<h2>Hello, {name}!</h2>
<button onClick={() => setName("John")}>Change Name</button>
</div>
);
}
When managing objects, spread operator (...) is used to update specific properties.
function UserInfo() {
const [user, setUser] = useState({ name: "Alice", age: 25 });
return (
<div>
<h2>Name: {user.name}</h2>
<h2>Age: {user.age}</h2>
<button onClick={() => setUser({ ...user, age: user.age + 1 })}>
Increase Age
</button>
</div>
);
}
function ItemList() {
const [items, setItems] = useState(["Apple", "Banana"]);
return (
<div>
<h2>Items:</h2>
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
<button onClick={() => setItems([...items, "Orange"])}>Add
Item</button>
</div>
);
}
If the new state depends on the previous state, use a callback function inside setState().
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<h2>Count: {count}</h2>
<button onClick={() => setCount(prevCount => prevCount + 1)}>
Increment
</button>
</div>
);
}
• Use the latest state when updating based on the previous value.
• Avoid directly mutating state objects (use spread operator).
• Use separate state variables for unrelated values.
• Use functional updates for performance optimization.
Conclusion
The useState hook is essential for handling state in functional components. It supports
numbers, strings, objects, and arrays. Using it properly ensures reactivity and efficient updates in
React applications.
React uses the map() function to iterate over an array and render a list of elements dynamically.
function ItemList() {
const items = ["Apple", "Banana", "Orange"];
return (
<ul>
{items.map((item, index) => (
<li key={index}>{item}</li>
))}
</ul>
);
}
Keys help React identify which items changed, added, or removed, optimizing re-rendering.
function UsersList() {
const users = [
{ id: 1, name: "Alice" },
{ id: 2, name: "Bob" },
{ id: 3, name: "Charlie" }
];
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
return (
<div>
<ul>
{tasks.map((task, index) => (
<li key={index}>{task}</li>
))}
</ul>
<button onClick={addTask}>Add Task</button>
</div>
);
}
function TaskList() {
const [tasks, setTasks] = useState(["Task 1", "Task 2", "Task 3"]);
return (
<div>
<ul>
{tasks.map((task, index) => (
<li key={index}>
{task}
<button onClick={() => removeTask(task)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
function UserList() {
const users = ["Alice", "Bob", "Charlie"];
return (
<ul>
{users.map((user, index) => (
<User key={index} name={user} />
))}
</ul>
);
}
Conclusion
Lists in React are managed using map(), and keys help React optimize rendering. Using unique
keys, state for dynamic lists, and filter() for deletions ensures efficient list management.
Props and Prop Drilling in React
Props (short for "properties") are a way to pass data from one component to another in React.
However, when deeply nested components need access to props, prop drilling becomes an issue.
Props allow components to receive data from their parent components and make React
components reusable.
function Greeting(props) {
return <h2>Hello, {props.name}!</h2>;
}
function App() {
return <Greeting name="Alice" />;
}
function App() {
return <UserProfile name="Bob" age={25} />;
}
Prop drilling occurs when props need to be passed down through multiple components to reach
a deeply nested child.
• The user prop is passed through Parent → Child → GrandChild, even though only
GrandChild needs it.
The Context API allows components to access values without manually passing props through
every level.
Example: Using Context API
import React, { createContext, useContext } from "react";
function App() {
const user = { name: "Charlie" };
return (
<UserContext.Provider value={user}>
<Parent />
</UserContext.Provider>
);
}
function Parent() {
return <Child />;
}
function Child() {
return <GrandChild />;
}
function GrandChild() {
const user = useContext(UserContext);
return <h2>User: {user.name}</h2>;
}
For larger applications, Redux or Zustand manage state globally, avoiding prop drilling.
Conclusion
Props allow data sharing between components, but prop drilling makes it inefficient when data
is needed deep in the component tree. Solutions like Context API and state management
libraries help prevent unnecessary prop passing.
Controlled Form Inputs in React
A controlled component in React is a form element (like an input, textarea, or select) whose
value is controlled by React state. This approach ensures that React handles the input's value and
updates the UI accordingly.
In a controlled component, the input value is managed using the useState hook. The component
re-renders whenever the state changes.
function ControlledInput() {
const [text, setText] = useState("");
return (
<div>
<input type="text" value={text} onChange={handleChange} />
<p>Input Value: {text}</p>
</div>
);
}
When dealing with multiple inputs, the state should store an object containing all field values.
function UserForm() {
const [formData, setFormData] = useState({ name: "", email: "" });
const handleChange = (event) => {
setFormData({ ...formData, [event.target.name]: event.target.value });
};
return (
<div>
<input type="text" name="name" value={formData.name}
onChange={handleChange} placeholder="Name" />
<input type="email" name="email" value={formData.email}
onChange={handleChange} placeholder="Email" />
<p>Name: {formData.name}</p>
<p>Email: {formData.email}</p>
</div>
);
}
When the form is submitted, we prevent the default behavior and handle the input values.
function SignupForm() {
const [formData, setFormData] = useState({ username: "", password: "" });
return (
<form onSubmit={handleSubmit}>
<input type="text" name="username" value={formData.username}
onChange={handleChange} placeholder="Username" />
<input type="password" name="password" value={formData.password}
onChange={handleChange} placeholder="Password" />
<button type="submit">Submit</button>
</form>
);
}
export default SignupForm;
function PreferencesForm() {
const [preferences, setPreferences] = useState({
gender: "male",
subscribe: false,
comments: "",
});
return (
<form>
<select name="gender" value={preferences.gender}
onChange={handleChange}>
<option value="male">Male</option>
<option value="female">Female</option>
</select>
<p>Gender: {preferences.gender}</p>
<p>Subscribed: {preferences.subscribe ? "Yes" : "No"}</p>
<p>Comments: {preferences.comments}</p>
</form>
);
}
• The select, checkbox, and textarea elements are controlled using state.
• The checked property manages checkboxes.
Conclusion
Controlled components keep form elements synchronized with React state, making data handling
easier. By using useState and event handlers, React efficiently manages input fields, multiple
values, and form submissions.
Here's a small React Form Handling Project that uses all the topics covered so far:
✅ Functional Components
✅ CSS Styling
✅ Click Events
✅ useState Hook
✅ Lists and Keys
✅ Props & Prop Drilling
✅ Controlled Form Inputs
Project Structure
/user-registration
├── src
│ ├── components
│ │ ├── UserForm.js
│ │ ├── UserList.js
│ │ ├── UserItem.js
│ ├── App.js
│ ├── index.js
├── package.json
├── public
├── README.md
1. UserForm.js (Controlled Form & Props)
return (
<form onSubmit={handleSubmit} className="user-form">
<input type="text" name="name" value={formData.name}
onChange={handleChange} placeholder="Enter Name" required />
<input type="email" name="email" value={formData.email}
onChange={handleChange} placeholder="Enter Email" required />
<button type="submit">Register</button>
</form>
);
}
• Maps through users and displays them using the UserItem component
• Prop drilling: users data is passed down
function App() {
const [users, setUsers] = useState([]);
return (
<div className="app">
<h1>User Registration</h1>
<UserForm addUser={addUser} />
<UserList users={users} />
</div>
);
}
body {
font-family: Arial, sans-serif;
background-color: #f4f4f4;
}
.app {
width: 50%;
margin: auto;
text-align: center;
}
.user-form {
display: flex;
flex-direction: column;
gap: 10px;
margin-bottom: 20px;
}
.user-form input {
padding: 8px;
font-size: 16px;
}
button {
background-color: #007bff;
color: white;
border: none;
padding: 10px;
cursor: pointer;
}
.user-list ul {
list-style: none;
padding: 0;
}
.user-item {
background-color: white;
margin: 5px;
padding: 10px;
border-radius: 5px;
}
Conclusion
Would you like any additional features like local storage or user deletion?
JSON Server is a lightweight, easy-to-use mock REST API that allows React applications to
perform CRUD operations (Create, Read, Update, Delete) using fetch or axios. It’s great for
prototyping and testing React projects.
Create a file named db.json in your project root and add sample data:
{
"users": [
{ "id": 1, "name": "John Doe", "email": "[email protected]" },
{ "id": 2, "name": "Jane Smith", "email": "[email protected]" }
]
}
Resources
http://localhost:5000/users
Now, you can send GET, POST, PUT, DELETE requests to http://localhost:5000/users.
Modify the User Registration Project to fetch and update users from JSON Server.
4.1 Fetching Users from JSON Server
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("http://localhost:5000/users")
.then((response) => response.json())
.then((data) => setUsers(data))
.catch((error) => console.error("Error fetching users:", error));
}, []);
return (
<div className="user-list">
<h2>Registered Users</h2>
<ul>
{users.map((user) => (
<UserItem key={user.id} user={user} />
))}
</ul>
</div>
);
}
return (
<form onSubmit={handleSubmit} className="user-form">
<input type="text" name="name" value={formData.name}
onChange={handleChange} placeholder="Enter Name" required />
<input type="email" name="email" value={formData.email}
onChange={handleChange} placeholder="Enter Email" required />
<button type="submit">Register</button>
</form>
);
}
return (
<li className="user-item">
{editing ? (
<>
<input type="text" value={updatedUser.name} onChange={(e) =>
setUpdatedUser({ ...updatedUser, name: e.target.value })} />
<input type="email" value={updatedUser.email} onChange={(e) =>
setUpdatedUser({ ...updatedUser, email: e.target.value })} />
<button onClick={handleUpdate}>Save</button>
</>
) : (
<>
<strong>{user.name}</strong> - {user.email}
<button onClick={() => setEditing(true)}>Edit</button>
</>
)}
</li>
);
}
<button onClick={handleDelete}>Delete</button>
function App() {
const [users, setUsers] = useState([]);
const fetchUsers = () => {
fetch("http://localhost:5000/users")
.then((response) => response.json())
.then((data) => setUsers(data))
.catch((error) => console.error("Error fetching users:", error));
};
useEffect(() => {
fetchUsers();
}, []);
return (
<div className="app">
<h1>User Registration</h1>
<UserForm refreshUsers={fetchUsers} />
<UserList users={users} refreshUsers={fetchUsers} />
</div>
);
}
Conclusion
Now, our React User Registration App is fully integrated with a REST API using JSON
Server. It supports:
✅ Fetching users (GET)
✅ Adding new users (POST)
✅ Updating user details (PUT)
✅ Deleting users (DELETE)
Fetching data from an API is an essential part of building dynamic React applications. React
provides various ways to fetch data, including using fetch API, Axios, and third-party libraries
like React Query.
1. Fetching Data with the Fetch API
Example: Fetching Users from JSONPlaceholder API
import React, { useState, useEffect } from "react";
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/users")
.then((response) => response.json())
.then((data) => setUsers(data))
.catch((error) => console.error("Error fetching data:", error));
}, []);
return (
<div>
<h2>Users List</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
Explanation
• useEffect(() => {}, []): Runs only once when the component mounts.
• fetch(): Makes a GET request to the API.
• .then(response => response.json()): Converts response to JSON.
• .then(data => setUsers(data)): Stores data in state.
• catch(error => console.error()): Handles errors.
Axios is a popular alternative to fetch(), providing better error handling and automatic JSON
conversion.
Installing Axios
npm install axios
Example Using Axios
import React, { useState, useEffect } from "react";
import axios from "axios";
function UserList() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get("https://jsonplaceholder.typicode.com/users")
.then(response => setUsers(response.data))
.catch(error => console.error("Error fetching data:", error));
}, []);
return (
<div>
<h2>Users List</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
Instead of fetching on page load, you can fetch data on user action (button click).
function FetchUsers() {
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(false);
return (
<div>
<button onClick={fetchData} disabled={loading}>
{loading ? "Loading..." : "Fetch Users"}
</button>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
Explanation
function UserList() {
const { data: users, error, isLoading } = useQuery({
queryKey: ["users"],
queryFn: async () => {
const response = await
axios.get("https://jsonplaceholder.typicode.com/users");
return response.data;
}
});
if (isLoading) return <p>Loading...</p>;
if (error) return <p>Error loading users.</p>;
return (
<div>
<h2>Users List</h2>
<ul>
{users.map((user) => (
<li key={user.id}>{user.name} - {user.email}</li>
))}
</ul>
</div>
);
}
Conclusion
Would you like an example of POST (creating new data) or DELETE (removing data)
requests as well?
CRUD (Create, Read, Update, Delete) operations are essential in any full-stack application. In
this guide, we'll build a React CRUD App using JSON Server as a fake REST API.
1. Setup JSON Server (Fake API)
Step 1: Install JSON Server
npm install -g json-server
Create a file named db.json in your project root and add sample data:
{
"users": [
{ "id": 1, "name": "John Doe", "email": "[email protected]" },
{ "id": 2, "name": "Jane Doe", "email": "[email protected]" }
]
}
We'll create a User Management System where users can be added, viewed, updated, and
deleted.
// Fetch Users
useEffect(() => {
axios.get("http://localhost:5000/users")
.then(response => setUsers(response.data))
.catch(error => console.error("Error fetching users:", error));
}, []);
// Delete User
const deleteUser = (id) => {
axios.delete(`http://localhost:5000/users/${id}`)
.then(() => setUsers(users.filter(user => user.id !== id)))
.catch(error => console.error("Error deleting user:", error));
};
return (
<div>
<h2>User List</h2>
<ul>
{users.map(user => (
<li key={user.id}>
{user.name} - {user.email}
<button onClick={() => onEdit(user)}>Edit</button>
<button onClick={() => deleteUser(user.id)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
Explanation
useEffect(() => {
if (selectedUser) {
setUser(selectedUser);
}
}, [selectedUser]);
// Handle Input Change
const handleChange = (e) => {
setUser({ ...user, [e.target.name]: e.target.value });
};
return (
<form onSubmit={handleSubmit}>
<h2>{user.id ? "Edit User" : "Add User"}</h2>
<input type="text" name="name" value={user.name}
onChange={handleChange} placeholder="Name" required />
<input type="email" name="email" value={user.email}
onChange={handleChange} placeholder="Email" required />
<button type="submit">{user.id ? "Update" : "Create"}</button>
</form>
);
}
Explanation
function App() {
const [selectedUser, setSelectedUser] = useState(null);
Explanation
Conclusion
This covers the full CRUD operations in React with JSON Server. Would you like to extend
this with a better UI using Material-UI or Tailwind CSS?
Here's a Fetch Data Challenge project that will help you practice API calls, state management,
and rendering data dynamically in React.
Project: User Data Fetcher
Goal:
function UserList() {
const [users, setUsers] = useState([]);
const [search, setSearch] = useState("");
const [page, setPage] = useState(1);
const [loading, setLoading] = useState(false);
useEffect(() => {
fetchUsers();
}, [page]);
return (
<div>
<h1>User List</h1>
<input
type="text"
placeholder="Search users..."
value={search}
onChange={(e) => setSearch(e.target.value)}
/>
<ul>
{users
.filter(user =>
user.name.first.toLowerCase().includes(search.toLowerCase()) ||
user.name.last.toLowerCase().includes(search.toLowerCase())
)
.map((user, index) => (
<li key={index}>
<img src={user.picture.thumbnail} alt={user.name.first} />
{user.name.first} {user.name.last} - {user.email}
</li>
))}
</ul>
<button onClick={loadMoreUsers} disabled={loading}>
{loading ? "Loading..." : "Load More Users"}
</button>
</div>
);
}
function App() {
return (
<div>
<UserList />
</div>
);
}
• Open http://localhost:3000
• Try searching for a user by first or last name.
• Click "Load More Users" to fetch more users.
Conclusion
Would you like to enhance this with pagination or a better UI using Tailwind CSS?
React Router is a library used to handle navigation in React applications. It enables single-page
applications (SPAs) to have multiple views without reloading the page.
ReactDOM.render(
<BrowserRouter>
<App />
</BrowserRouter>,
document.getElementById("root")
);
3. Create Pages
(1) Home Page (Home.js)
import React from "react";
function Home() {
return <h1>Welcome to the Home Page</h1>;
}
function About() {
return <h1>About Us</h1>;
}
function Contact() {
return <h1>Contact Us</h1>;
}
function App() {
return (
<div>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
</Routes>
</div>
);
}
function Navbar() {
return (
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link> |
<Link to="/contact">Contact</Link>
</nav>
);
}
• Open http://localhost:3000
• Click on "About" or "Contact" in the navbar to navigate.
Conclusion
Would you like to add protected routes (authentication-based) or a 404 Not Found page?
React Router Hooks & Links
React Router provides various hooks and <Link> components to navigate between pages
dynamically.
function Home() {
const navigate = useNavigate();
return (
<div>
<h1>Home Page</h1>
<button onClick={() => navigate("/about")}>Go to About</button>
</div>
);
}
function CurrentLocation() {
const location = useLocation();
function Navbar() {
return (
<nav>
<Link to="/">Home</Link> |
<Link to="/about">About</Link> |
<Link to="/contact">Contact</Link>
</nav>
);
}
function Navbar() {
return (
<nav>
<NavLink to="/" style={({ isActive }) => ({ fontWeight: isActive ?
"bold" : "normal" })}>
Home
</NavLink> |
<NavLink to="/about" style={({ isActive }) => ({ fontWeight: isActive ?
"bold" : "normal" })}>
About
</NavLink> |
<NavLink to="/contact" style={({ isActive }) => ({ fontWeight: isActive
? "bold" : "normal" })}>
Contact
</NavLink>
</nav>
);
}
function App() {
return (
<div>
<Navbar />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/contact" element={<Contact />} />
<Route path="/user/:id" element={<User />} />
</Routes>
</div>
);
}
• Open http://localhost:3000
• Click on links to navigate between pages.
• Try /user/123 in the browser.
Conclusion
In React, you can set width and height using inline styles, CSS classes, styled-components, or
Tailwind CSS.
styles.css
.box {
width: 250px;
height: 120px;
background-color: lightgreen;
text-align: center;
line-height: 120px;
}
Apply in Component
import React from "react";
import "./styles.css";
function Box() {
return <div className="box">CSS Styled Box</div>;
}
Install styled-components:
npm install styled-components
function Box() {
return <StyledBox>Styled Components Box</StyledBox>;
}
Install Tailwind:
function Box() {
return <div className="w-64 h-32 bg-blue-500 text-white text-center flex
items-center justify-center">Tailwind Box</div>;
}
Conclusion
Axios is a popular library for making HTTP requests in React. It supports GET, POST, PUT,
DELETE requests and handles errors efficiently.
1. Install Axios
function FetchData() {
const [data, setData] = useState([]);
useEffect(() => {
axios.get("https://jsonplaceholder.typicode.com/posts")
.then((response) => setData(response.data))
.catch((error) => console.error("Error fetching data:", error));
}, []);
return (
<div>
<h2>Posts</h2>
{data.slice(0, 5).map((post) => (
<p key={post.id}>{post.title}</p>
))}
</div>
);
}
function CreatePost() {
const [title, setTitle] = useState("");
return (
<div>
<input type="text" value={title} onChange={(e) =>
setTitle(e.target.value)} placeholder="Enter title" />
<button onClick={handleSubmit}>Create Post</button>
</div>
);
}
function UpdatePost() {
const [title, setTitle] = useState("");
return (
<div>
<input type="text" value={title} onChange={(e) =>
setTitle(e.target.value)} placeholder="Update title" />
<button onClick={handleUpdate}>Update Post</button>
</div>
);
}
function DeletePost() {
const handleDelete = async () => {
try {
await axios.delete("https://jsonplaceholder.typicode.com/posts/1");
console.log("Post Deleted");
} catch (error) {
console.error("Error deleting post:", error);
}
};
function App() {
return (
<div>
<FetchData />
<CreatePost />
<UpdatePost />
<DeletePost />
</div>
);
}
Conclusion
Would you like to integrate loading states or error handling for better UX?
A custom hook is a reusable function in React that encapsulates logic using built-in hooks like
useState, useEffect, or useContext. It helps reduce code duplication and improves
maintainability.
Let's create a hook to fetch data from an API using useEffect and useState.
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
setLoading(true);
axios.get(url)
.then((response) => {
setData(response.data);
setLoading(false);
})
.catch((error) => {
setError(error);
setLoading(false);
});
}, [url]);
function PostList() {
const { data, loading, error } =
useFetch("https://jsonplaceholder.typicode.com/posts");
return (
<div>
<h2>Posts</h2>
{data.slice(0, 5).map((post) => (
<p key={post.id}>{post.title}</p>
))}
</div>
);
}
useEffect(() => {
localStorage.setItem(key, JSON.stringify(value));
}, [key, value]);
function Counter() {
const [count, setCount] = useLocalStorage("count", 0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
function useForm(initialValues) {
const [values, setValues] = useState(initialValues);
function LoginForm() {
const { values, handleChange } = useForm({ email: "", password: "" });
return (
<div>
<input type="email" name="email" value={values.email}
onChange={handleChange} placeholder="Email" />
<input type="password" name="password" value={values.password}
onChange={handleChange} placeholder="Password" />
<button>Submit</button>
</div>
);
}
A custom hook is a reusable function that allows us to encapsulate logic using React hooks like
useState, useEffect, and useRef. Combining Axios and async/await inside useEffect makes
API calls more efficient and reusable across multiple components.
This hook handles GET, POST, PUT, DELETE requests using Axios.
useEffect(() => {
const fetchData = async () => {
setLoading(true);
try {
let response;
if (method === "GET") {
response = await axios.get(url);
} else if (method === "POST") {
response = await axios.post(url, body);
} else if (method === "PUT") {
response = await axios.put(url, body);
} else if (method === "DELETE") {
response = await axios.delete(url);
}
setData(response.data);
} catch (err) {
setError(err);
}
setLoading(false);
};
fetchData();
}, dependencies);
function PostList() {
const { data, loading, error } =
useAxios("https://jsonplaceholder.typicode.com/posts");
return (
<div>
<h2>Posts</h2>
{data.slice(0, 5).map((post) => (
<p key={post.id}>{post.title}</p>
))}
</div>
);
}
function CreatePost() {
const [title, setTitle] = useState("");
const { data, loading, error } = useAxios(
"https://jsonplaceholder.typicode.com/posts",
"POST",
{ title, body: "New Post", userId: 1 },
[title]
);
return (
<div>
<input type="text" value={title} onChange={(e) =>
setTitle(e.target.value)} placeholder="Enter title" />
<button disabled={loading}>Create Post</button>
{error && <p>Error creating post!</p>}
{data && <p>Post Created: {data.title}</p>}
</div>
);
}
function UpdateDeletePost() {
const updateData = { title: "Updated Title", body: "Updated Content",
userId: 1 };
const { data: updatedPost, error: updateError } = useAxios(
"https://jsonplaceholder.typicode.com/posts/1",
"PUT",
updateData,
[]
);
return (
<div>
{updateError && <p>Error updating post!</p>}
{updatedPost && <p>Post Updated: {updatedPost.title}</p>}
function App() {
return (
<div>
<PostList />
<CreatePost />
<UpdateDeletePost />
</div>
);
}
Conclusion
Would you like to extend this hook for pagination or authentication tokens?
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
The useReducer hook is useful for complex state logic involving multiple actions.
function Counter() {
const [state, dispatch] = useReducer(reducer, { count: 0 });
return (
<div>
<p>Count: {state.count}</p>
<button onClick={() => dispatch({ type: "INCREMENT"
})}>Increment</button>
<button onClick={() => dispatch({ type: "DECREMENT"
})}>Decrement</button>
</div>
);
}
The Context API allows global state sharing without prop drilling.
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
function ThemeToggle() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<div>
<p>Current Theme: {theme}</p>
<button onClick={toggleTheme}>Toggle Theme</button>
</div>
);
}
function App() {
return (
<ThemeProvider>
<ThemeToggle />
</ThemeProvider>
);
}
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById("root")
);
function Counter() {
const count = useSelector((state) => state.counter.count);
const dispatch = useDispatch();
return (
<div>
<p>Count: {count}</p>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
</div>
);
}
function Counter() {
const [count, setCount] = useRecoilState(counterState);
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}
function App() {
return (
<RecoilRoot>
<Counter />
</RecoilRoot>
);
}
React Redux
Redux is a state management library used in React applications to manage global state
efficiently. It follows a centralized state management approach, making it easier to handle data
across multiple components.
A slice represents a piece of the state and defines actions to modify it.
The store holds the global state and integrates all reducers.
Wrap the entire application with Provider to enable Redux state management.
Modify index.js:
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import { store } from "./store";
import Counter from "./Counter";
ReactDOM.render(
<Provider store={store}>
<Counter />
</Provider>,
document.getElementById("root")
);
4. Use Redux in a Component
Step 1: Create Counter Component (Counter.js)
function Counter() {
const count = useSelector((state) => state.counter.count);
const dispatch = useDispatch();
return (
<div>
<h2>Counter: {count}</h2>
<button onClick={() => dispatch(increment())}>Increment</button>
<button onClick={() => dispatch(decrement())}>Decrement</button>
<button onClick={() => dispatch(incrementByAmount(5))}>Increment by
5</button>
</div>
);
}
Middleware like Redux Thunk is used for handling asynchronous operations like API calls.
function UserList() {
const dispatch = useDispatch();
const { users, loading } = useSelector((state) => state.users);
useEffect(() => {
dispatch(fetchUsers());
}, [dispatch]);
return (
<div>
<h2>User List</h2>
{loading ? <p>Loading...</p> : users.map((user) => <p
key={user.id}>{user.name}</p>)}
</div>
);
}
Conclusion
Key Concepts in Redux:
1. Prerequisites
• A GitHub account.
• Node.js and npm installed.
• A React project set up using create-react-app.
• A GitHub repository to push your project.
Open your terminal and navigate to your React project folder, then install the gh-pages package:
3. Configure package.json
Modify your package.json file to include the homepage URL and deployment scripts.
Replace your-username and your-repository with your actual GitHub username and
repository name.
"homepage": "https://your-username.github.io/your-repository"
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
If your project is not already a Git repository, initialize it and push it to GitHub:
git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/your-username/your-repository.git
git push -u origin main
This will build the project and push the build folder to the gh-pages branch.
https://your-username.github.io/your-repository
Conclusion
GitHub Pages provides a free and easy way to host React apps.
gh-pages automates the deployment process.
Any updates can be pushed and redeployed with npm run deploy.