diff --git a/Writerside/images/zustand.png b/Writerside/images/zustand.png new file mode 100644 index 0000000..fc3015e Binary files /dev/null and b/Writerside/images/zustand.png differ diff --git a/Writerside/pdfSourceR.html b/Writerside/pdfSourceR.html index 9400cf7..eab8b97 100644 --- a/Writerside/pdfSourceR.html +++ b/Writerside/pdfSourceR.html @@ -273,7 +273,7 @@ .topic { page-break-before: always; } -
Here is the course outline for a React.js and TypeScript documentation written in Markdown (.md) format:
Overview of React
Benefits of using React
Introduction to TypeScript in React
Setting up the Development Environment
Installing Node.js and npm
Setting up a React project with Create React App (CRA) or Vite
Configuring TypeScript in a React Project
JSX & Props
What is JSX?
Embedding JavaScript in JSX
Passing Props to Components
Using Props for Reusable Components
Components in React
Functional vs. Class Components
Creating Components with TypeScript
Default and Named Exports
Rendering Components
useState Hook
Introduction to useState
Managing State in Functional Components
Example: Managing Form Inputs
useReducer Hook
Introduction to useReducer
Complex State Management
Example: Building a Counter with useReducer
Handling Events
Event Handling in React
Passing Parameters to Event Handlers
Common Event Handlers (e.g., onClick, onChange, onSubmit)
Conditional Rendering
Using Ternary Operators for Conditional Rendering
Best Practices for Conditional Rendering
Rendering Lists
Mapping Data to Components
Understanding Keys in React
Handling Dynamic Lists
Introduction to Hooks
What are Hooks?
Rules of Hooks
useEffect Hook
Synchronizing with External Systems
Fetching Data with useEffect
Dependency Arrays
useRef Hook
Managing DOM References
Persisting Values Across Renders
Example: Counting Renders
Introduction to Custom Hooks
When and Why to Create Custom Hooks
Naming Conventions
Creating a Custom Hook
Example: useLocalStorage Hook
Example: useFetch Hook
Memoization in React
What is Memoization?
useMemo Hook
useCallback Hook
React.memo for Component Optimization
Avoiding Prop Drilling
Issues with Prop Drilling
Solutions: Context API, Redux, Component Composition
Introduction to Redux
Centralized State Management
Benefits of Redux
Setting Up Redux Toolkit
Installing Redux Toolkit
Creating a Redux Store
Using createSlice and configureStore
Handling Asynchronous Actions
Using createAsyncThunk for Async Operations
Integrating with Redux Slices
RTK Query for Data Fetching
Introduction to RTK Query
Queries and Mutations in RTK Query
Handling Caching and Error States
Introduction to React Router
Setting Up React Router
Basic Routing Concepts
Nested Routes and URL Parameters
React Router DOM V6
New Features in React Router V6
Route Protection with Private Routes
Handling 404 Pages
Introduction to React Hook Form
Why Use React Hook Form?
Setting Up React Hook Form
Handling Form Validation with Yup
Advanced Form Handling
Dynamic Forms
Handling Form Submissions
Preparing for Deployment
Optimizing Your React App for Production
Managing Environment Variables
Deployment Strategies
Deploying to Vercel, Netlify, and Azure
Continuous Integration/Continuous Deployment (CI/CD) with GitHub Actions
Code Structuring
Organizing Files and Folders
Naming Conventions and Best Practices
Avoiding Common Mistakes
Managing State and Props Effectively
Ensuring Performance Optimization
Handling Errors Gracefully
Recap of Key Concepts
Further Learning Resources
Next Steps in React and TypeScript Mastery
Before you start, you should have a basic understanding of:
[x] What is HTML
[x] What is CSS
[x] What is DOM
[x] What is ES6
[x] What is Node.js
[x] What is npm
React, sometimes referred to as a frontend JavaScript framework, is a JavaScript library created by Facebook.
React is a tool for building UI components.
React has solidified its position as the go-to JavaScript front-end framework in the current tech landscape. It’s fascinating to see how it’s seamlessly woven itself into the development practices of well-established corporations and budding startups alike.
Web development :
This is where React got its start and where you’ll find it used most often. React is component-based. An example of a component could be a form or even just a form field or button on a website. In React, you build up complete applications using components like these by nesting them.
Components in React can manage their own state and communicate that state to child components. By “state,” we mean the data that populates the web application.
Mobile app development :
React Native is a JavaScript framework that uses React. With React Native, developers can apply web-based React principles to creating mobile apps for Android and iOS. Here, React is used to connect the mobile user interface of the application to the phone’s operating system.
Desktop app development :
Developers can also use React with Electron, another JavaScript library, to create cross-platform desktop apps. Some apps you may know about that are built with Electron include Visual Studio Code, Slack, Skype, Discord, WhatsApp, and WordPress Desktop.
React.js, a popular JavaScript library for building user interfaces, particularly for single-page applications, has a fascinating history that reflects its evolution and growing adoption in the web development community. Here's a brief history of React.js in bullet points:
2011: React.js created by Facebook's Jordan Walke for internal use.
2013: Open-sourced at JSConf US; introduced virtual DOM.
2014: Facebook introduced Flux, influencing state management in React.
2015: React Native launched, expanding React to mobile apps.
2015: React v0.14 split core into react and react-dom.
2016: React v15 brought performance improvements and prop-types.
2017: React Fiber (v16) restructured core for better responsiveness.
2018: Hooks introduced in v16.8, transforming component design.
2019: Experimental Suspense and Concurrent Mode introduced.
2020: React v17 focused on easier upgrades.
2022: React 18 brought full Concurrent Mode and enhanced UI responsiveness.
2023: React 19 is the latest major release of the React JavaScript library, bringing a range of new features and improvements aimed at enhancing both developer experience and application performance. Some of the key updates include:
React Compiler: A significant new feature, the React Compiler automates many performance optimizations, like memoization, which were previously handled manually using hooks like useMemo and useCallback. This simplifies the code and makes React apps faster and more efficient.
Actions and Form Handling: React 19 introduces a new way to handle form submissions and state changes using "Actions." This feature simplifies managing asynchronous operations, making it easier to handle loading states, errors, and successful form submissions.
New Hooks: Several new hooks have been introduced, such as useOptimistic, which allows for optimistic UI updates (i.e., updating the UI immediately while awaiting server confirmation), and use, which simplifies asynchronous operations within components. Additionally, the useFormStatus and useActionState hooks make managing form state more intuitive.
Server Components: React 19 enhances server-side rendering by allowing server components, similar to features in frameworks like Next.js. This can lead to faster page loads and improved SEO.
Improved Metadata Management: Managing document metadata like titles and meta tags is now easier and more integrated into React components, eliminating the need for third-party libraries like react-helmet.
Background Asset Loading: React 19 introduces background loading of assets (like images and scripts), which helps improve page load times and overall user experience by preloading resources in the background as users navigate through the app.
"Thinking in React" is a concept that describes the process of designing and building user interfaces with React.js. It emphasizes breaking down the UI into components, managing data flow, and structuring the application in a way that aligns with React's component-based architecture. Here’s a concise breakdown:
Start with a Mockup: Look at your UI and identify the different parts that can be broken down into components.
Imagine that you already have a JSON API and a mockup from a designer.
The JSON API returns some data that looks like this:
[
+ Table of contents
Course Outline: React with TypeScript Documentation
Here is the course outline for a React.js and TypeScript documentation written in Markdown (.md) format:
1. Introduction to React
Overview of React
Benefits of using React
Introduction to TypeScript in React
Setting up the Development Environment
Installing Node.js and npm
Setting up a React project with Create React App (CRA) or Vite
Configuring TypeScript in a React Project
2. Core Concepts
JSX & Props
What is JSX?
Embedding JavaScript in JSX
Passing Props to Components
Using Props for Reusable Components
Components in React
Functional vs. Class Components
Creating Components with TypeScript
Default and Named Exports
Rendering Components
3. State Management
useState Hook
Introduction to useState
Managing State in Functional Components
Example: Managing Form Inputs
useReducer Hook
Introduction to useReducer
Complex State Management
Example: Building a Counter with useReducer
4. Advanced React Concepts
Handling Events
Event Handling in React
Passing Parameters to Event Handlers
Common Event Handlers (e.g., onClick, onChange, onSubmit)
Conditional Rendering
Using Ternary Operators for Conditional Rendering
Best Practices for Conditional Rendering
Rendering Lists
Mapping Data to Components
Understanding Keys in React
Handling Dynamic Lists
5. Hooks in React
Introduction to Hooks
What are Hooks?
Rules of Hooks
useEffect Hook
Synchronizing with External Systems
Fetching Data with useEffect
Dependency Arrays
useRef Hook
Managing DOM References
Persisting Values Across Renders
Example: Counting Renders
6. Custom Hooks
Introduction to Custom Hooks
When and Why to Create Custom Hooks
Naming Conventions
Creating a Custom Hook
Example: useLocalStorage Hook
Example: useFetch Hook
7. Performance Optimization
Memoization in React
What is Memoization?
useMemo Hook
useCallback Hook
React.memo for Component Optimization
Avoiding Prop Drilling
Issues with Prop Drilling
Solutions: Context API, Redux, Component Composition
8. Advanced State Management with Redux Toolkit
Introduction to Redux
Centralized State Management
Benefits of Redux
Setting Up Redux Toolkit
Installing Redux Toolkit
Creating a Redux Store
Using createSlice and configureStore
Handling Asynchronous Actions
Using createAsyncThunk for Async Operations
Integrating with Redux Slices
RTK Query for Data Fetching
Introduction to RTK Query
Queries and Mutations in RTK Query
Handling Caching and Error States
9. Routing with React Router
Introduction to React Router
Setting Up React Router
Basic Routing Concepts
Nested Routes and URL Parameters
React Router DOM V6
New Features in React Router V6
Route Protection with Private Routes
Handling 404 Pages
10. Form Management with React Hook Form & Yup
Introduction to React Hook Form
Why Use React Hook Form?
Setting Up React Hook Form
Handling Form Validation with Yup
Advanced Form Handling
Dynamic Forms
Handling Form Submissions
11. Deploying React Applications
Preparing for Deployment
Optimizing Your React App for Production
Managing Environment Variables
Deployment Strategies
Deploying to Vercel, Netlify, and Azure
Continuous Integration/Continuous Deployment (CI/CD) with GitHub Actions
12. Best Practices and Common Pitfalls
Code Structuring
Organizing Files and Folders
Naming Conventions and Best Practices
Avoiding Common Mistakes
Managing State and Props Effectively
Ensuring Performance Optimization
Handling Errors Gracefully
13. Conclusion
Recap of Key Concepts
Further Learning Resources
Next Steps in React and TypeScript Mastery
1. Intro to React
1.1 Overview of React
React Quickstart
Before you start, you should have a basic understanding of:
[x] What is HTML
[x] What is CSS
[x] What is DOM
[x] What is ES6
[x] What is Node.js
[x] What is npm
What is React?
React, sometimes referred to as a frontend JavaScript framework, is a JavaScript library created by Facebook.
React is a tool for building UI components.
React has solidified its position as the go-to JavaScript front-end framework in the current tech landscape. It’s fascinating to see how it’s seamlessly woven itself into the development practices of well-established corporations and budding startups alike.
What is React used for?
Web development :
This is where React got its start and where you’ll find it used most often. React is component-based. An example of a component could be a form or even just a form field or button on a website. In React, you build up complete applications using components like these by nesting them.
Components in React can manage their own state and communicate that state to child components. By “state,” we mean the data that populates the web application.
Mobile app development :
React Native is a JavaScript framework that uses React. With React Native, developers can apply web-based React principles to creating mobile apps for Android and iOS. Here, React is used to connect the mobile user interface of the application to the phone’s operating system.
Desktop app development :
Developers can also use React with Electron, another JavaScript library, to create cross-platform desktop apps. Some apps you may know about that are built with Electron include Visual Studio Code, Slack, Skype, Discord, WhatsApp, and WordPress Desktop.
React.JS History
React.js, a popular JavaScript library for building user interfaces, particularly for single-page applications, has a fascinating history that reflects its evolution and growing adoption in the web development community. Here's a brief history of React.js in bullet points:
2011: React.js created by Facebook's Jordan Walke for internal use.
2013: Open-sourced at JSConf US; introduced virtual DOM.
2014: Facebook introduced Flux, influencing state management in React.
2015: React Native launched, expanding React to mobile apps.
2015: React v0.14 split core into react and react-dom.
2016: React v15 brought performance improvements and prop-types.
2017: React Fiber (v16) restructured core for better responsiveness.
2018: Hooks introduced in v16.8, transforming component design.
2019: Experimental Suspense and Concurrent Mode introduced.
2020: React v17 focused on easier upgrades.
2022: React 18 brought full Concurrent Mode and enhanced UI responsiveness.
2023: React 19 is the latest major release of the React JavaScript library, bringing a range of new features and improvements aimed at enhancing both developer experience and application performance. Some of the key updates include:
React Compiler: A significant new feature, the React Compiler automates many performance optimizations, like memoization, which were previously handled manually using hooks like useMemo and useCallback. This simplifies the code and makes React apps faster and more efficient.
Actions and Form Handling: React 19 introduces a new way to handle form submissions and state changes using "Actions." This feature simplifies managing asynchronous operations, making it easier to handle loading states, errors, and successful form submissions.
New Hooks: Several new hooks have been introduced, such as useOptimistic, which allows for optimistic UI updates (i.e., updating the UI immediately while awaiting server confirmation), and use, which simplifies asynchronous operations within components. Additionally, the useFormStatus and useActionState hooks make managing form state more intuitive.
Server Components: React 19 enhances server-side rendering by allowing server components, similar to features in frameworks like Next.js. This can lead to faster page loads and improved SEO.
Improved Metadata Management: Managing document metadata like titles and meta tags is now easier and more integrated into React components, eliminating the need for third-party libraries like react-helmet.
Background Asset Loading: React 19 introduces background loading of assets (like images and scripts), which helps improve page load times and overall user experience by preloading resources in the background as users navigate through the app.
1.2 Thinking in React
"Thinking in React" is a concept that describes the process of designing and building user interfaces with React.js. It emphasizes breaking down the UI into components, managing data flow, and structuring the application in a way that aligns with React's component-based architecture. Here’s a concise breakdown:
1. Break Down the UI into Components
Start with a Mockup: Look at your UI and identify the different parts that can be broken down into components.
Imagine that you already have a JSON API and a mockup from a designer.
The JSON API returns some data that looks like this:
[
{ category: "Fruits", price: "$1", stocked: true, name: "Apple" },
{ category: "Fruits", price: "$1", stocked: true, name: "Dragonfruit" },
{ category: "Fruits", price: "$2", stocked: false, name: "Passionfruit" },
@@ -3501,7 +3501,7 @@
);
}
-export default App;
Step 6: Running the Application
Start your application with:
npm run dev or pnpm run dev
Handling Asynchronous Actions
Redux Toolkit (Thunk)
In many applications, we need to perform asynchronous operations such as fetching data from an API, posting data to a server, or dealing with side effects like authentication and file uploads. Redux Toolkit provides a simple and powerful way to handle these scenarios through thunks, which are async functions that dispatch actions.
Using createAsyncThunk from Redux Toolkit, you can handle async operations efficiently while managing loading, success, and error states.
Project Overview: Fetching Data from an API
Let's build a small project that focuses on handling asynchronous actions using Redux Toolkit. This project will demonstrate:
Fetching a list of posts from a public API (jsonplaceholder.typicode.com).
Managing loading, success, and error states for the async action.
Displaying the fetched data in a React component.
Best practices for structuring and managing async actions.
Key Concepts:
Thunk: A function that delays its execution or dispatches other functions (async functions).
createAsyncThunk: A Redux Toolkit method to handle async logic and automatically dispatch actions based on the promise state (pending, fulfilled, rejected).
1. Project Setup
Initialize the Project:
Use Vite with React and TypeScript.
npm create vite@latest async-redux-app -- --template react-ts
+export default App;
Step 6: Running the Application
Start your application with:
npm run dev or pnpm run dev
Redux Thunk - Handling Asynchronous Actions
Redux Toolkit (Thunk)
In many applications, we need to perform asynchronous operations such as fetching data from an API, posting data to a server, or dealing with side effects like authentication and file uploads. Redux Toolkit provides a simple and powerful way to handle these scenarios through thunks, which are async functions that dispatch actions.
Using createAsyncThunk from Redux Toolkit, you can handle async operations efficiently while managing loading, success, and error states.
Project Overview: Fetching Data from an API
Let's build a small project that focuses on handling asynchronous actions using Redux Toolkit. This project will demonstrate:
Fetching a list of posts from a public API (jsonplaceholder.typicode.com).
Managing loading, success, and error states for the async action.
Displaying the fetched data in a React component.
Best practices for structuring and managing async actions.
Key Concepts:
Thunk: A function that delays its execution or dispatches other functions (async functions).
createAsyncThunk: A Redux Toolkit method to handle async logic and automatically dispatch actions based on the promise state (pending, fulfilled, rejected).
1. Project Setup
Initialize the Project:
Use Vite with React and TypeScript.
npm create vite@latest async-redux-app -- --template react-ts
cd async-redux-app
npm install
Install Redux Toolkit and React Redux:
npm install @reduxjs/toolkit react-redux axios
Folder Structure:
We’ll organize our code to follow best practices with a clear separation of concerns.
src/
├── components/
@@ -3660,7 +3660,7 @@
);
};
-export default App;
6. Running the Application
You can now run the application using:
npm run dev
Open the browser at http://localhost:5173 to see the fetched posts.
Explanation of Best Practices
Using createAsyncThunk:
We used createAsyncThunk to handle the lifecycle of async operations. This is a best practice in Redux Toolkit as it helps to reduce boilerplate and automatically handles the states of a promise.
Service Layer:
We created a postService.ts file that encapsulates the API logic. This decouples business logic from the Redux slice, making the code cleaner and easier to maintain.
Separation of Concerns:
We separated concerns by using redux/ for state management, services/ for API
End2End: React ReduxThunk ExpressMongoDb Posts CRUD APP
This is a fully functional CRUD app using TypeScript for both the Express backend and the React frontend. The backend will use MongoDB for storing posts, and the frontend will use **Redux Toolkit(Thunk) ** to interact with the API for managing CRUD operations.
Step 1: Setting Up the Backend with Express, MongoDB, and TypeScript
1.1 Backend Folder Structure
Here's the folder structure for the TypeScript-based Express backend:
backend/
+export default App;
6. Running the Application
You can now run the application using:
npm run dev
Open the browser at http://localhost:5173 to see the fetched posts.
Explanation of Best Practices
Using createAsyncThunk:
We used createAsyncThunk to handle the lifecycle of async operations. This is a best practice in Redux Toolkit as it helps to reduce boilerplate and automatically handles the states of a promise.
Service Layer:
We created a postService.ts file that encapsulates the API logic. This decouples business logic from the Redux slice, making the code cleaner and easier to maintain.
Separation of Concerns:
We separated concerns by using redux/ for state management, services/ for API
End2End: React ReduxThunk ExpressMongoDb Posts CRUD APP
This is a fully functional CRUD app using TypeScript for both the Express backend and the React frontend. The backend will use MongoDB for storing posts, and the frontend will use **Redux Toolkit(Thunk) ** to interact with the API for managing CRUD operations.
Step 1: Setting Up the Backend with Express, MongoDB, and TypeScript
1.1 Backend Folder Structure
Here's the folder structure for the TypeScript-based Express backend:
backend/
├── src/
│ ├── config/
│ │ └── db.ts
@@ -3674,11 +3674,11 @@
├── .env
├── tsconfig.json
├── package.json
-└── package-lock.json
1.2 Backend Dependencies
First, set up your backend by initializing a Node.js project with TypeScript support:
mkdir backend
+└── package-lock.json
1.2 Backend Dependencies
First, set up your backend by initializing a Node.js project with TypeScript support:
mkdir backend
cd backend
npm init -y
npm install express mongoose dotenv cors
-npm install --save-dev Typescript tsx @types/node @types/cors
1.3 TypeScript Configuration
Create a tsconfig.json file in the backend root:
{
+npm install --save-dev Typescript tsx @types/node @types/cors
1.3 TypeScript Configuration
Create a tsconfig.json file in the backend root:
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
@@ -3688,7 +3688,7 @@
"outDir": "./dist"
},
"include": ["src/**/*"]
-}
1.4 MongoDB Connection
Create a new folder called config/ and a file db.ts for connecting to MongoDB:
File: src/config/db.ts
import mongoose from 'mongoose';
+}
1.4 MongoDB Connection
Create a new folder called config/ and a file db.ts for connecting to MongoDB:
File: src/config/db.ts
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
@@ -3703,7 +3703,7 @@
}
};
-export default connectDB;
File: .env
Add your MongoDB connection string:
MONGO_URI=mongodb://localhost:27017/posts
1.5 Create Post Model
Define the Post model that corresponds to the structure of posts in the MongoDB database.
File: src/models/postModel.ts
import mongoose, { Schema, Document } from 'mongoose';
+export default connectDB;
File: .env
Add your MongoDB connection string:
MONGO_URI=mongodb://localhost:27017/posts
1.5 Create Post Model
Define the Post model that corresponds to the structure of posts in the MongoDB database.
File: src/models/postModel.ts
import mongoose, { Schema, Document } from 'mongoose';
export interface IPost extends Document {
title: string;
@@ -3717,7 +3717,7 @@
const Post = mongoose.model<IPost>('Post', postSchema);
-export default Post;
1.6 Create Post Controller
The controller will handle the logic for each API endpoint.
File: src/controllers/postController.ts
import { Request, Response } from 'express';
+export default Post;
1.6 Create Post Controller
The controller will handle the logic for each API endpoint.
File: src/controllers/postController.ts
import { Request, Response } from 'express';
import Post, { IPost } from '../models/postModel';
// Fetch all posts
@@ -3776,7 +3776,7 @@
} catch (error) {
res.status(500).json({ message: 'Server error' });
}
-};
1.7 Create Routes for Posts
We define the API routes for performing CRUD operations on posts.
File: src/routes/postRoutes.ts
import express from 'express';
+};
1.7 Create Routes for Posts
We define the API routes for performing CRUD operations on posts.
File: src/routes/postRoutes.ts
import express from 'express';
import { getPosts, createPost, updatePost, deletePost } from '../controllers/postController';
const router = express.Router();
@@ -3784,7 +3784,7 @@
router.route('/').get(getPosts).post(createPost);
router.route('/:id').put(updatePost).delete(deletePost);
-export default router;
1.8 Initialize Express Server
Now let's create the main server file and set up middleware.
File: src/server.ts
import express from 'express';
+export default router;
1.8 Initialize Express Server
Now let's create the main server file and set up middleware.
File: src/server.ts
import express from 'express';
import cors from 'cors';
import dotenv from 'dotenv';
import connectDB from './config/db';
@@ -3804,7 +3804,7 @@
const PORT = process.env.PORT || 5000;
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
-});
Run the backend server:
npm run dev
Step 2: Setting Up the Frontend (React + Redux Toolkit)
Now let's connect the backend API to a React + Redux Toolkit frontend.
2.1 Frontend Folder Structure
frontend/
+});
Run the backend server:
npm run dev
Step 2: Setting Up the Frontend (React + Redux Toolkit)
Now let's connect the backend API to a React + Redux Toolkit frontend.
2.1 Frontend Folder Structure
frontend/
├── src/
│ ├── components/
│ │ └── PostList.tsx
@@ -3821,11 +3821,11 @@
│ └── main.tsx
├── tsconfig.json
├── package.json
-└── package-lock.json
2.2 Frontend Dependencies
Initialize the frontend using Vite with TypeScript:
mkdir frontend
+└── package-lock.json
2.2 Frontend Dependencies
Initialize the frontend using Vite with TypeScript:
mkdir frontend
cd frontend
npm create vite@latest async-frontend -- --template react-ts
cd async-frontend
-npm install
Install required packages:
npm install @reduxjs/toolkit react-redux axios lucide-react
2.3 Redux Setup for Posts (CRUD Actions)
Post Service:
Path: src/features/posts/services/postService.ts
import axios from 'axios';
+npm install
Install required packages:
npm install @reduxjs/toolkit react-redux axios lucide-react
2.3 Redux Setup for Posts (CRUD Actions)
Post Service:
Path: src/features/posts/services/postService.ts
import axios from 'axios';
const API_URL = 'http://localhost:5000/api/posts';
@@ -3847,7 +3847,7 @@
export const deletePost = async (id: string) => {
const response = await axios.delete(`${API_URL}/${id}`);
return response.data;
-};
Redux Slice:
Path: src/features/posts/redux/postSlice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
+};
Redux Slice:
Path: src/features/posts/redux/postSlice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import { fetchPosts, createPost, updatePost, deletePost } from '../services/postService';
interface Post {
@@ -3926,7 +3926,7 @@
},
});
-export default postSlice.reducer;
Store Configuration:
Path: src/store/store.ts
import { configureStore } from '@reduxjs/toolkit';
+export default postSlice.reducer;
Store Configuration:
Path: src/store/store.ts
import { configureStore } from '@reduxjs/toolkit';
import postReducer from '../features/posts/redux/postSlice';
const store = configureStore({
@@ -3938,7 +3938,7 @@
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
-export default store;
2.4 React Components to Manage Posts
Post List Component:
Path: src/components/PostList.tsx
import React, { useEffect } from 'react';
+export default store;
2.4 React Components to Manage Posts
Post List Component:
Path: src/components/PostList.tsx
import React, { useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { fetchPostsThunk, deletePostThunk } from '../features/posts/redux/postSlice';
import { RootState, AppDispatch } from '../store/store';
@@ -3967,7 +3967,7 @@
);
};
-export default PostList;
Post Form Component:
path src/components/PostForm.tsx
import React, { useState } from 'react';
+export default PostList;
Post Form Component:
path src/components/PostForm.tsx
import React, { useState } from 'react';
import { useDispatch } from 'react-redux';
import { createPostThunk } from '../features/posts/redux/postSlice';
import { AppDispatch } from '../store/store';
@@ -4029,7 +4029,7 @@
);
};
-export default PostForm;
App Component:
Path: src/App.tsx
import React from 'react';
+export default PostForm;
App Component:
Path: src/App.tsx
import React from 'react';
import PostList from './components/PostList';
const App = () => {
@@ -4041,9 +4041,9 @@
);
};
-export default App;
Step 3: Running the Full Stack Application
Run the Backend:
cd backend
-npm run dev
Run the Frontend:
cd frontend
-npm run dev
Open your browser at http://localhost:5173/ to view the app. The app will fetch, display, create, update, and delete posts with full CRUD functionality using React + Redux Toolkit for the frontend and Express + MongoDB for the backend.
This setup provides a clean, scalable way to manage async actions in Redux, ensuring best practices are followed throughout the stack.
RTK Query for Data Fetching
What is RTK Query?
RTK Query is a powerful data-fetching and caching tool that is built directly into Redux Toolkit. It simplifies the process of data fetching in Redux applications by abstracting away many of the complexities that come with handling loading, caching, re-fetching, and synchronizing server state.
Unlike traditional Redux approaches (using thunk), which require you to manually manage async operations, RTK Query does a lot of the heavy lifting for you.
Benefits of Using RTK Query
Automatic Caching: RTK Query automatically caches your API responses and avoids unnecessary network requests. When data is fetched, it stores that data and serves it on subsequent requests until it's invalidated.
Simplicity: RTK Query abstracts much of the boilerplate code you'd typically write with redux-thunk. You no longer need to manage loading, error, or success states manually.
Optimized Performance: It efficiently handles state updates and only re-fetches data when necessary (e.g., when cache expiration happens).
Automatic Refetching: If a component relies on a particular piece of data, RTK Query can automatically re-fetch that data when necessary, such as when a dependent component is re-rendered or when the cache becomes stale.
Code Reusability: You can define API endpoints once and then use them across multiple components without re-writing data fetching logic.
RTK Query Main Architecture and Components
createApi:
This is the core function in RTK Query. It defines your endpoints (API operations such as GET, POST, PUT, and DELETE) and how your application interacts with the backend.
Example: Defining API endpoints for fetching posts, creating a post, and deleting a post.
Base Query:
baseQuery is a function that acts as the low-level fetcher for your endpoints. Typically, this will use fetch or axios to make HTTP requests. RTK Query allows you to customize baseQuery for all your API operations.
Example: You can configure a global axios instance or fetch to handle authentication tokens, error handling, and more.
Endpoints:
Endpoints represent the actual API operations such as GET /posts, POST /users, etc. Each endpoint defines how data is fetched, updated, or deleted.
Hooks:
RTK Query automatically generates React hooks for every endpoint. These hooks are used inside your React components to trigger data fetching, mutation (POST, PUT, DELETE), and cache handling.
Best Way to Use RTK Query
Define API Services in a Centralized Place: Create a central API slice where you define all endpoints and configuration.
Leverage Auto-Generated Hooks: RTK Query automatically provides hooks (e.g., useGetPostsQuery, useAddPostMutation) which you can use in your components to interact with the API.
Cache Management: Use RTK Query's built-in cache management to optimize performance. You can manually invalidate the cache when needed.
Error Handling: RTK Query includes mechanisms for automatic error handling, but you can also customize and intercept errors globally in the baseQuery.
RTK Query Vs Redux Thunk
In redux we typically model network fetching and caching like this.
You have a component, which subscribes to data from the redux store via selectors
In a useEffect hook you check if the data doesn’t exist and then dispatch a thunk
Your thunk will use a tool like fetch or axios to grab data from over the network
As it fetches data your thunk will dispatch actions into the redux store such as pending, fulfilled and rejected (error).
This is complicated to setup and maintain
RTK Query provides a better way.
RTK Query generates hooks for you at runtime that allow you to query and cache data or run mutations. Loading and error states are available automatically in your component via the hook and cache invalidation is easily manageable.
This diagram illustrates the difference between handling cached data and fetching network data using Redux Thunk and RTK Query.
Let's break down each part:
Top Left: Invalidating Cached Data (Redux)
With Redux and Thunk, to invalidate cached data or refresh data, you have to handle it manually:
You dispatch an action via a thunk or use useEffect in the component to trigger data invalidation.
You manually dispatch actions to refetch or invalidate specific data.
This requires handling the logic for when and how to refresh the cached data, often involving multiple steps.
Top Middle: Using Cached Data (Redux)
With Redux, when you want to reuse cached data across components:
The data is stored in the Redux store.
Components access the cached data using selectors.
If the data is already available in the store, components simply render the cached data without needing to refetch.
The challenge is managing cache invalidation and ensuring that data is still up-to-date.
Top Right: Fetching & Caching Network Data (Redux + Thunk)
In this case:
You use a Thunk action to fetch data (e.g., with fetch or axios).
You dispatch actions to initiate the request, handle loading, and update the Redux store with the fetched data.
Selectors are used to access the data in components.
Components also use useEffect or other hooks to trigger the fetching action at the right time (e.g., on mount or user interaction).
This approach works but requires manual management of when to fetch, update, and cache data.
Bottom Left: Invalidating Cached Data (RTK Query)
With RTK Query, invalidating cached data is simplified:
RTK Query provides automatic cache management via tags and automatic data refetching based on the tags.
The component simply interacts with the API layer provided by RTK Query through custom hooks (useQuery, useMutation), and RTK Query handles the caching and invalidation logic.
You don’t need to manually dispatch actions for invalidating or refetching data—RTK Query does it based on its cache policies.
Bottom Middle: Using Cached Data (RTK Query)
With RTK Query, using cached data is seamless:
Components use custom query hooks (auto-generated by RTK Query) to access data.
The data is fetched and cached by RTK Query, and any subsequent renders or components that need the same data will automatically use the cached version.
No manual management is needed; RTK Query handles caching internally.
Bottom Right: Fetching & Caching Network Data (RTK Query)
RTK Query abstracts away much of the complexity:
RTK Query handles everything: it automatically caches, refetches, and synchronizes data across your components.
You simply call the API via query hooks in your components, and RTK Query takes care of dispatching actions, fetching data, storing it in Redux, and managing loading and error states.
The message "THINGS YOU NO LONGER HAVE TO WORRY ABOUT" in the diagram indicates that RTK Query eliminates the need for manually managing cache invalidation, error handling, and re-fetching logic.
Summary of the Diagram
Redux with Thunk: You need to manually handle actions, thunks, cache invalidation, and re-fetching data when needed. It provides flexibility but requires more boilerplate code and management.
RTK Query: Simplifies the data fetching and caching process by automatically managing cache invalidation, re-fetching, and keeping data up-to-date. It provides hooks for fetching and mutating data, while abstracting away many complexities like caching and syncing server state with the Redux store.
End2End: React RTK Query ExpressMongoDb Posts CRUD APP
Let's create a full-stack CRUD application to store user profiles using React + Redux Toolkit Query on the frontend and Express + MongoDB on the backend.
Backend Setup (Express + MongoDB + TypeScript)
1. Backend Folder Structure:
backend/
+export default App;
Step 3: Running the Full Stack Application
Run the Backend:
cd backend
+npm run dev
Run the Frontend:
cd frontend
+npm run dev
Open your browser at http://localhost:5173/ to view the app. The app will fetch, display, create, update, and delete posts with full CRUD functionality using React + Redux Toolkit for the frontend and Express + MongoDB for the backend.
This setup provides a clean, scalable way to manage async actions in Redux, ensuring best practices are followed throughout the stack.
RTK Query - Data Fetching
What is RTK Query?
RTK Query is a powerful data-fetching and caching tool that is built directly into Redux Toolkit. It simplifies the process of data fetching in Redux applications by abstracting away many of the complexities that come with handling loading, caching, re-fetching, and synchronizing server state.
Unlike traditional Redux approaches (using thunk), which require you to manually manage async operations, RTK Query does a lot of the heavy lifting for you.
Benefits of Using RTK Query
Automatic Caching: RTK Query automatically caches your API responses and avoids unnecessary network requests. When data is fetched, it stores that data and serves it on subsequent requests until it's invalidated.
Simplicity: RTK Query abstracts much of the boilerplate code you'd typically write with redux-thunk. You no longer need to manage loading, error, or success states manually.
Optimized Performance: It efficiently handles state updates and only re-fetches data when necessary (e.g., when cache expiration happens).
Automatic Refetching: If a component relies on a particular piece of data, RTK Query can automatically re-fetch that data when necessary, such as when a dependent component is re-rendered or when the cache becomes stale.
Code Reusability: You can define API endpoints once and then use them across multiple components without re-writing data fetching logic.
RTK Query Main Architecture and Components
createApi:
This is the core function in RTK Query. It defines your endpoints (API operations such as GET, POST, PUT, and DELETE) and how your application interacts with the backend.
Example: Defining API endpoints for fetching posts, creating a post, and deleting a post.
Base Query:
baseQuery is a function that acts as the low-level fetcher for your endpoints. Typically, this will use fetch or axios to make HTTP requests. RTK Query allows you to customize baseQuery for all your API operations.
Example: You can configure a global axios instance or fetch to handle authentication tokens, error handling, and more.
Endpoints:
Endpoints represent the actual API operations such as GET /posts, POST /users, etc. Each endpoint defines how data is fetched, updated, or deleted.
Hooks:
RTK Query automatically generates React hooks for every endpoint. These hooks are used inside your React components to trigger data fetching, mutation (POST, PUT, DELETE), and cache handling.
Best Way to Use RTK Query
Define API Services in a Centralized Place: Create a central API slice where you define all endpoints and configuration.
Leverage Auto-Generated Hooks: RTK Query automatically provides hooks (e.g., useGetPostsQuery, useAddPostMutation) which you can use in your components to interact with the API.
Cache Management: Use RTK Query's built-in cache management to optimize performance. You can manually invalidate the cache when needed.
Error Handling: RTK Query includes mechanisms for automatic error handling, but you can also customize and intercept errors globally in the baseQuery.
RTK Query Vs Redux Thunk
In redux we typically model network fetching and caching like this.
You have a component, which subscribes to data from the redux store via selectors
In a useEffect hook you check if the data doesn’t exist and then dispatch a thunk
Your thunk will use a tool like fetch or axios to grab data from over the network
As it fetches data your thunk will dispatch actions into the redux store such as pending, fulfilled and rejected (error).
This is complicated to setup and maintain
RTK Query provides a better way.
RTK Query generates hooks for you at runtime that allow you to query and cache data or run mutations. Loading and error states are available automatically in your component via the hook and cache invalidation is easily manageable.
This diagram illustrates the difference between handling cached data and fetching network data using Redux Thunk and RTK Query.
Let's break down each part:
Top Left: Invalidating Cached Data (Redux)
With Redux and Thunk, to invalidate cached data or refresh data, you have to handle it manually:
You dispatch an action via a thunk or use useEffect in the component to trigger data invalidation.
You manually dispatch actions to refetch or invalidate specific data.
This requires handling the logic for when and how to refresh the cached data, often involving multiple steps.
Top Middle: Using Cached Data (Redux)
With Redux, when you want to reuse cached data across components:
The data is stored in the Redux store.
Components access the cached data using selectors.
If the data is already available in the store, components simply render the cached data without needing to refetch.
The challenge is managing cache invalidation and ensuring that data is still up-to-date.
Top Right: Fetching & Caching Network Data (Redux + Thunk)
In this case:
You use a Thunk action to fetch data (e.g., with fetch or axios).
You dispatch actions to initiate the request, handle loading, and update the Redux store with the fetched data.
Selectors are used to access the data in components.
Components also use useEffect or other hooks to trigger the fetching action at the right time (e.g., on mount or user interaction).
This approach works but requires manual management of when to fetch, update, and cache data.
Bottom Left: Invalidating Cached Data (RTK Query)
With RTK Query, invalidating cached data is simplified:
RTK Query provides automatic cache management via tags and automatic data refetching based on the tags.
The component simply interacts with the API layer provided by RTK Query through custom hooks (useQuery, useMutation), and RTK Query handles the caching and invalidation logic.
You don’t need to manually dispatch actions for invalidating or refetching data—RTK Query does it based on its cache policies.
Bottom Middle: Using Cached Data (RTK Query)
With RTK Query, using cached data is seamless:
Components use custom query hooks (auto-generated by RTK Query) to access data.
The data is fetched and cached by RTK Query, and any subsequent renders or components that need the same data will automatically use the cached version.
No manual management is needed; RTK Query handles caching internally.
Bottom Right: Fetching & Caching Network Data (RTK Query)
RTK Query abstracts away much of the complexity:
RTK Query handles everything: it automatically caches, refetches, and synchronizes data across your components.
You simply call the API via query hooks in your components, and RTK Query takes care of dispatching actions, fetching data, storing it in Redux, and managing loading and error states.
The message "THINGS YOU NO LONGER HAVE TO WORRY ABOUT" in the diagram indicates that RTK Query eliminates the need for manually managing cache invalidation, error handling, and re-fetching logic.
Summary of the Diagram
Redux with Thunk: You need to manually handle actions, thunks, cache invalidation, and re-fetching data when needed. It provides flexibility but requires more boilerplate code and management.
RTK Query: Simplifies the data fetching and caching process by automatically managing cache invalidation, re-fetching, and keeping data up-to-date. It provides hooks for fetching and mutating data, while abstracting away many complexities like caching and syncing server state with the Redux store.
End2End: React RTK Query ExpressMongoDb Posts CRUD APP
Let's create a full-stack CRUD application to store user profiles using React + Redux Toolkit Query on the frontend and Express + MongoDB on the backend.
Backend Setup (Express + MongoDB + TypeScript)
1. Backend Folder Structure:
backend/
├── src/
│ ├── config/
│ │ └── db.ts
@@ -4395,4 +4395,437 @@
export default App;
Final Steps to Run the Application
Run the Backend:
cd backend
npm run dev
Run the Frontend:
cd frontend
-npm run dev
Open the frontend at http://localhost:5175/. The app will fetch, create, update, and delete user profiles, fully utilizing RTK Query to handle the frontend's API interaction and caching.
Key Features of RTK Query in This Application:
Efficient Caching: RTK Query caches all user data and only re-fetches if the data becomes invalidated.
Simplified Data Fetching: The useGetUsersQuery, useAddUserMutation, useDeleteUserMutation, and useUpdateUserMutation hooks handle the API requests without manually managing loading or error states.
Auto-Generated Hooks: The API slice automatically provides reusable hooks, making it easier to manage CRUD operations for users.
This setup shows how you can build a scalable, performant, and modern full-stack CRUD application using RTK Query and Redux Toolkit for efficient data fetching and management.