React
Debugging
Double Rendering
- In the Development environment components two times render because of React.StrictMode but not in production
React Developer Tools
Redux Devtool
- Add chrome extension Redux devtool
- install
npm I redux-devtools-extension - wrap inside
composeWithDevTools
Profiler
- go in profile and update setting for reson for re render
- start recroding
- change state means do any operation which will change state
- stop recording and you can see why each compone re render
React Query Dev Tool
Install @tanstack/react-query-devtools
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
Immutable Operations in React
Add object to array
const newBook = {
id: 6,
title: "Harry Potter and the Chamber of Secrets",
author: "J. K. Rowling",
};
const booksAfterAdd = [...books, newBook];
function handleAddItems(item) {
setItems((items) => [...items, item]);
}
Delete book object from array
const booksAfterDelete = booksAfterAdd.filter((book) => book.id !== 3);
function handleDeleteItem(id) {
setItems((items) => items.filter((item) => item.id !== id));
}
Update book object in the array
const booksAfterUpdate = booksAfterDelete.map((book) =>
book.id === 1 ? { ...book, pages: 1210 } : book
);
function handleToggleItem(id) {
setItems((items) =>
items.map((item) =>
item.id === id ? { ...item, packed: !item.packed } : item
)
);
}
Add property in Object
const originalObject = { foo: 'bar' };
const newObject = { ...originalObject, baz: 'qux' };
console.log(originalObject); // Output: { foo: 'bar' }
console.log(newObject); // Output: { foo: 'bar', baz: 'qux' }
Update a property in Object
const originalObject = { foo: 'bar', baz: 'qux' };
const updatedObject = { ...originalObject, baz: 'updated value' };
console.log(originalObject); // Output: { foo: 'bar', baz: 'qux' }
console.log(updatedObject); // Output: { foo: 'bar', baz: 'updated value' }
Deletea property in Object
const originalObject = { foo: 'bar', baz: 'qux' };
const { baz, ...newObject } = originalObject;
console.log(originalObject); // Output: { foo: 'bar', baz: 'qux' }
console.log(newObject); // Output: { foo: 'bar' }
JSX
- {} this one for putting js in html
- ${} this one is for putting into js string
import React from "react";
import ReactDOM from "react-dom";
const name = "jitu";
const fullName = `${name} birla`;
console.log(fullName);
ReactDOM.render(<h1>Hello World! {name}</h1>, document.getElementById("root"));
JSX Attributes and Styling
- alt + click for mutiple select and edit
- We have use JavaScript attribute for html element like camelCase
className - React Styling Practice
import React from "react";
import ReactDOM from "react-dom";
const img = "https://picsum.photos/200";
ReactDOM.render(
<div>
<h1 className="heading">My Favourite Foods</h1>
<img alt="random" src={img + "?grayscale"} />
</div>,
document.getElementById("root")
);
//-------------------------------------------------------
import React from "react";
import ReactDOM from "react-dom";
const customStyle = {
color: "red",
fontSize: "20px",
border: "1px solid black"
};
customStyle.color = "blue";
ReactDOM.render(
<div>
<h1 style={{ color: "red" }}>Hello World!</h1>,
<h1 style={customStyle}>Hello World!</h1>
</div>,
document.getElementById("root")
);
Styling options in React App
Conditional Rendering in JSX
Using &&
- This will execute anything when isOpen will true and it work with truthy and falsy values
- //5 falsy values: 0, '', undefined, null, NaN
isOpen && <anything>
Using ternary operator
numPizzas > 0 ? when true :when false
Multiple Returns
if (pizzaObj.soldOut) return null;
retrun(
<div>
asdsad
</div>
)
Using Style Property
<div style={{ display: showInfo ? "block" : "none" }}>info</div>
Props
Get all the props in props object or deconstruct at the time of receiving args
<Pizza pizzaObj={pizza} key={pizza.name} jd="birla" />
function Pizza(props) {
console.log(props);
/* {
"pizzaObj": {
"name": "Pizza Prosciutto",
"ingredients": "Tomato, mozarella, ham, aragula, and burrata cheese",
"price": 18,
"photoName": "pizzas/prosciutto.jpg",
"soldOut": false
},
"jd": "birla"
-----
birla
}*/
function Pizza({ pizzaObj }) {}
Children Prop
Passing element (jsx) as prop
- it alternative to children's prop
State
Always update state using callback
if (step < 3) {
setStep((s) => s + 1); // Correct way
// setStep(step + 1); //incorrect way
}
State uplifting
export default function App() {
const [items, setItems] = useState([]);
function handleAddItems(item) {
setItems((items) => [...items, item]);
}
<Form onAddItems={handleAddItems} />
<PackingList
items={items}
/>
}
export default function Form({ onAddItems }) {
onAddItems(newItem);
}
Derived State
Hooks
useEffect
- Sideeffect must be run in evenhandler or useEffect not in render logic
- useEffect always executes after browser paint
- Every state variable and prop used inside the effect MUST be included in the dependency array
- cleaning up a data fetching
useEffect(
function () {
const controller = new AbortController();
async function fetchMovies() {
try {
setIsLoading(true);
setError("");
const res = await fetch(
`http://www.omdbapi.com/?apikey=${KEY}&s=${query}`,
{ signal: controller.signal }
);
if (!res.ok)
throw new Error("Something went wrong with fetching movies");
const data = await res.json();
if (data.Response === "False") throw new Error("Movie not found");
setMovies(data.Search);
setError("");
} catch (err) {
if (err.name !== "AbortError") {
console.log(err.message);
setError(err.message);
}
} finally {
setIsLoading(false);
}
}
if (query.length < 3) {
setMovies([]);
setError("");
return;
}
handleCloseMovie();
fetchMovies();
return function () {
controller.abort();
};
},
[query]
);
useRef
- How not to select DOM element in react
custom Hooks
useReducer
useParams
- This hooks help in getting param value from URL in react router
useSearchParams
- This hook helps in getting and setting queryString values in URL
useNavigate
- This hook helps us in automatically navigation and back navigation
useContext
- This hook help child componet of provider to subcribe the context and get the value from providers
const { onClearPosts } = useContext(PostContext);
Rendering
- React reacts to state changes by re-rendering the UI
- Rendering or re-rendering basically executes the component function
- Child component Re-render when props changed by parent
React Router
- Routing
<BrowserRouter>
<Suspense fallback={<SpinnerFullPage />}>
<Routes>
<Route index element={<Homepage />} />
<Route path="product" element={<Product />} />
<Route path="pricing" element={<Pricing />} />
<Route path="login" element={<Login />} />
<Route
path="app"
element={
<ProtectedRoute>
<AppLayout />
</ProtectedRoute>
}
>
<Route index element={<Navigate replace to="cities" />} />
<Route path="cities" element={<CityList />} />
<Route path="cities/:id" element={<City />} />
<Route path="countries" element={<CountryList />} />
<Route path="form" element={<Form />} />
</Route>
<Route path="*" element={<PageNotFound />} />
</Routes>
</Suspense>
</BrowserRouter>
- Navingation using Link and Navlink
- The
component extends the functionality of by providing additional features specifically for styling and active class assignment. It adds an extra CSS class to the rendered element when it matches the current URL, allowing you to apply custom styles to the active link.
<nav className={styles.nav}>
<Logo />
<ul>
<li>
<NavLink to="/pricing">Pricing</NavLink>
</li>
<li>
<NavLink to="/product">Product</NavLink>
</li>
<li>
<NavLink to="/login" className={styles.ctaLink}>
Login
</NavLink>
</li>
</ul>
</nav>
Nested Routes
- in the above Routing you can check app link which has nested routing
- All the components of app router will render inside
<AppLayout />we can put it anywhere inside the app layout or child of<AppLayout />component using<Outlet />tag
URL for State Management
for Param
- http://localhost:5173/app/cities/17806751
// create new route
<Route path="cities/:id" element={<City />} />
// Create link on items
<Link
className={`${styles.cityItem} ${
id === currentCity.id ? styles["cityItem--active"] : ""
}`}
to={`${id}`}
>
// get that param value in componnet `<City />`
const { id } = useParams();
<Link
className={`${styles.cityItem} ${
id === currentCity.id ? styles["cityItem--active"] : ""
}`}
to={`${id}`}
For Query String
// create link
<Link
className={`${styles.cityItem} ${
id === currentCity.id ? styles["cityItem--active"] : ""
}`}
to={`${id}?lat=${position.lat}&lng=${position.lng}`}
>
// get the query string data
const [searchParams, setSearchParams] = useSearchParams();
const lat = searchParams.get("lat");
const lng = searchParams.get("lng");
Programmatic navigation
- Navigate automatically from one page to another page and even back in history
- Ex1
const navigate = useNavigate();
navigate("/app/cities");
- Ex2
function BackButton() {
const navigate = useNavigate();
return (
<Button
type="back"
onClick={(e) => {
e.preventDefault();
navigate(-1);
}}
>
← Back
</Button>
);
}
Context API
- Context api mostly using by Custom Provider
- Create seprate context file
- Create custome componet like below
PostProvidercreate context obejct in the file - Put all your state logic here which we have to pass in all child components
- Return
<PostContext.Provider value={value}>{children}</PostContext.Provider>whree value will be value object which contains all the states and function which are required for child components - Create custom hook for
useContextso that all subscribe can direcly use this custom hook and no required foruseContexthook
function createRandomPost() {
return {
title: `${faker.hacker.adjective()} ${faker.hacker.noun()}`,
body: faker.hacker.phrase(),
};
}
// 1) CREATE A CONTEXT
const PostContext = createContext();
function PostProvider({ children }) {
const [posts, setPosts] = useState(() =>
Array.from({ length: 30 }, () => createRandomPost())
);
const [searchQuery, setSearchQuery] = useState("");
// Derived state. These are the posts that will actually be displayed
const searchedPosts =
searchQuery.length > 0
? posts.filter((post) =>
`${post.title} ${post.body}`
.toLowerCase()
.includes(searchQuery.toLowerCase())
)
: posts;
function handleAddPost(post) {
setPosts((posts) => [post, ...posts]);
}
function handleClearPosts() {
setPosts([]);
}
const value = useMemo(() => {
return {
posts: searchedPosts,
onAddPost: handleAddPost,
onClearPosts: handleClearPosts,
searchQuery,
setSearchQuery,
};
}, [searchedPosts, searchQuery]);
return (
// 2) PROVIDE VALUE TO CHILD COMPONENTS
<PostContext.Provider value={value}>{children}</PostContext.Provider>
);
}
function usePosts() {
const context = useContext(PostContext);
if (context === undefined)
throw new Error("PostContext was used outside of the PostProvider");
return context;
}
export { PostProvider, usePosts };
//------------------------------------------
// 3) CONSUMING CONTEXT VALUE
const { onClearPosts } = usePosts();
Authentication
- Create login context
- Use that login xontext in login , logout components
- Create a protected componet and wrappe whole application inside the protected component
import { createContext, useContext, useReducer } from "react";
const AuthContext = createContext();
const initialState = {
user: null,
isAuthenticated: false,
};
function reducer(state, action) {
switch (action.type) {
case "login":
return { ...state, user: action.payload, isAuthenticated: true };
case "logout":
return { ...state, user: null, isAuthenticated: false };
default:
throw new Error("Unknown action");
}
}
const FAKE_USER = {
name: "Jack",
email: "jack@example.com",
password: "qwerty",
avatar: "https://i.pravatar.cc/100?u=zz",
};
function AuthProvider({ children }) {
const [{ user, isAuthenticated }, dispatch] = useReducer(
reducer,
initialState
);
function login(email, password) {
if (email === FAKE_USER.email && password === FAKE_USER.password)
dispatch({ type: "login", payload: FAKE_USER });
}
function logout() {
dispatch({ type: "logout" });
}
return (
<AuthContext.Provider value={{ user, isAuthenticated, login, logout }}>
{children}
</AuthContext.Provider>
);
}
function useAuth() {
const context = useContext(AuthContext);
if (context === undefined)
throw new Error("AuthContext was used outside AuthProvider");
return context;
}
export { AuthProvider, useAuth };
- Protected component
import { useEffect } from "react";
import { useNavigate } from "react-router-dom";
import { useAuth } from "../contexts/FakeAuthContext";
function ProtectedRoute({ children }) {
const { isAuthenticated } = useAuth();
const navigate = useNavigate();
useEffect(
function () {
if (!isAuthenticated) navigate("/login");
},
[isAuthenticated, navigate]
);
return isAuthenticated ? children : null;
}
export default ProtectedRoute;
- Wrapping application in protected component
<Route
path="app"
element={
<ProtectedRoute>
<AppLayout />
</ProtectedRoute>
}
>
<Route index element={<Navigate replace to="cities" />} />
<Route path="cities" element={<CityList />} />
<Route path="cities/:id" element={<City />} />
<Route path="countries" element={<CountryList />} />
<Route path="form" element={<Form />} />
</Route>
Redux
Redux in Isolation without react using classic redux
- We can't change state and no asynchronous logic
import { combineReducers, createStore } from "redux";
const initialStateAccount = {
balance: 0,
loan: 0,
loanPurpose: "",
};
const initialStateCustomer = {
fullName: "",
nationalID: "",
createdAt: "",
};
function accountReducer(state = initialStateAccount, action) {
switch (action.type) {
case "account/deposit":
return { ...state, balance: state.balance + action.payload };
case "account/withdraw":
return { ...state, balance: state.balance - action.payload };
case "account/requestLoan":
if (state.loan > 0) return state;
// LATER
return {
...state,
loan: action.payload.amount,
loanPurpose: action.payload.purpose,
balance: state.balance + action.payload.amount,
};
case "account/payLoan":
return {
...state,
loan: 0,
loanPurpose: "",
balance: state.balance - state.loan,
};
default:
return state;
}
}
function customerReducer(state = initialStateCustomer, action) {
switch (action.type) {
case "customer/createCustomer":
return {
...state,
fullName: action.payload.fullName,
nationalID: action.payload.nationalID,
createdAt: action.payload.createdAt,
};
case "customer/updateName":
return { ...state, fullName: action.payload };
default:
return state;
}
}
const rootReducer = combineReducers({
account: accountReducer,
customer: customerReducer,
});
const store = createStore(rootReducer);
// store.dispatch({ type: "account/deposit", payload: 500 });
// store.dispatch({ type: "account/withdraw", payload: 200 });
// console.log(store.getState());
// store.dispatch({
// type: "account/requestLoan",
// payload: { amount: 1000, purpose: "Buy a car" },
// });
// console.log(store.getState());
// store.dispatch({ type: "account/payLoan" });
// console.log(store.getState());
// const ACOOUNT_DEPOSIT = "account/deposit";
function deposit(amount) {
return { type: "account/deposit", payload: amount };
}
function withdraw(amount) {
return { type: "account/withdraw", payload: amount };
}
function requestLoan(amount, purpose) {
return {
type: "account/requestLoan",
payload: { amount, purpose },
};
}
function payLoan() {
return { type: "account/payLoan" };
}
store.dispatch(deposit(500));
store.dispatch(withdraw(200));
console.log(store.getState());
store.dispatch(requestLoan(1000, "Buy a cheap car"));
console.log(store.getState());
store.dispatch(payLoan());
console.log(store.getState());
function createCustomer(fullName, nationalID) {
return {
type: "customer/createCustomer",
payload: { fullName, nationalID, createdAt: new Date().toISOString() },
};
}
function updateName(fullName) {
return { type: "account/updateName", payload: fullName };
}
store.dispatch(createCustomer("Jonas Schmedtmann", "24343434"));
store.dispatch(deposit(250));
console.log(store.getState());
Create a slice of the store based on features
React- redux
- Connect redux with react
import React from "react";
import ReactDOM from "react-dom/client";
import { Provider } from "react-redux";
import "./index.css";
import App from "./App";
import store from "./store";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
//------------------------------------------------------
import { applyMiddleware, combineReducers, createStore } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import accountReducer from "./features/accounts/accountSlice";
import customerReducer from "./features/customers/customerSlice";
const rootReducer = combineReducers({
account: accountReducer,
customer: customerReducer,
});
const store = createStore(
rootReducer
);
export default store;
//------------------------------------------------------
import { useSelector } from "react-redux";
function Customer() {
const customer = useSelector((store) => store.customer.fullName);
return <h2>👋 Welcome, {customer}</h2>;
}
export default Customer;
//------------------------------------------------------
const dispatch = useDispatch();
function handleClick() {
if (!fullName || !nationalId) return;
dispatch(createCustomer(fullName, nationalId));
}
Redux Middleware
- For Asynchronous API call
- For thunk we should call sync function before returning the dispatch function in action creator funciton
- accountslice.js
export default function accountReducer(state = initialState, action) {
switch (action.type) {
case "account/deposit":
return {
...state,
balance: state.balance + action.payload,
isLoading: false,
};
case "account/withdraw":
return { ...state, balance: state.balance - action.payload };
case "account/requestLoan":
if (state.loan > 0) return state;
// LATER
return {
...state,
loan: action.payload.amount,
loanPurpose: action.payload.purpose,
balance: state.balance + action.payload.amount,
};
case "account/payLoan":
return {
...state,
loan: 0,
loanPurpose: "",
balance: state.balance - state.loan,
};
case "account/convertingCurrency":
return { ...state, isLoading: true };
default:
return state;
}
}
export function deposit(amount, currency) {
if (currency === "USD") return { type: "account/deposit", payload: amount };
return async function (dispatch, getState) {
dispatch({ type: "account/convertingCurrency" });
const res = await fetch(
`https://api.frankfurter.app/latest?amount=${amount}&from=${currency}&to=USD`
);
const data = await res.json();
const converted = data.rates.USD;
dispatch({ type: "account/deposit", payload: converted });
};
}
export function withdraw(amount) {
return { type: "account/withdraw", payload: amount };
}
export function requestLoan(amount, purpose) {
return {
type: "account/requestLoan",
payload: { amount, purpose },
};
}
export function payLoan() {
return { type: "account/payLoan" };
}
- store.js
import { applyMiddleware, combineReducers, createStore } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import accountReducer from "./features/accounts/accountSlice";
import customerReducer from "./features/customers/customerSlice";
const rootReducer = combineReducers({
account: accountReducer,
customer: customerReducer,
});
const store = createStore(
rootReducer,
composeWithDevTools(applyMiddleware(thunk))
);
export default store;
Reduxc Tool Kit
- Modern way to write redux code
- We can write code that “mutates” state inside reducers (will be converted to immutable logic behind the scenes by “Immer” library)
-
Action creators are automatically created and Automatic setup of thunk middleware and DevTools
-
accountslice.js
import { createSlice } from "@reduxjs/toolkit";
const initialState = {
balance: 0,
loan: 0,
loanPurpose: "",
isLoading: false,
};
const accountSlice = createSlice({
name: "account",
initialState,
reducers: {
deposit(state, action) {
state.balance += action.payload;
state.isLoading = false;
},
withdraw(state, action) {
state.balance -= action.payload;
},
requestLoan: {
prepare(amount, purpose) {
return {
payload: { amount, purpose },
};
},
reducer(state, action) {
if (state.loan > 0) return;
state.loan = action.payload.amount;
state.loanPurpose = action.payload.purpose;
state.balance = state.balance + action.payload.amount;
},
},
payLoan(state) {
state.balance -= state.loan;
state.loan = 0;
state.loanPurpose = "";
},
convertingCurrency(state) {
state.isLoading = true;
},
},
});
export const { withdraw, requestLoan, payLoan } = accountSlice.actions;
export function deposit(amount, currency) {
if (currency === "USD") return { type: "account/deposit", payload: amount };
return async function (dispatch, getState) {
dispatch({ type: "account/convertingCurrency" });
const res = await fetch(
`https://api.frankfurter.app/latest?amount=${amount}&from=${currency}&to=USD`
);
const data = await res.json();
const converted = data.rates.USD;
dispatch({ type: "account/deposit", payload: converted });
};
}
export default accountSlice.reducer;
- store.js
import { configureStore } from "@reduxjs/toolkit";
import accountReducer from "./features/accounts/accountSlice";
import customerReducer from "./features/customers/customerSlice";
const store = configureStore({
reducer: {
account: accountReducer,
customer: customerReducer,
},
});
export default store;
- AccountOperation.js
import { useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { deposit, payLoan, requestLoan, withdraw } from "./accountSlice";
function AccountOperations() {
const [depositAmount, setDepositAmount] = useState("");
const [withdrawalAmount, setWithdrawalAmount] = useState("");
const [loanAmount, setLoanAmount] = useState("");
const [loanPurpose, setLoanPurpose] = useState("");
const [currency, setCurrency] = useState("USD");
const dispatch = useDispatch();
const {
loan: currentLoan,
loanPurpose: currentLoanPurpose,
balance,
isLoading,
} = useSelector((store) => store.account);
console.log(balance);
function handleDeposit() {
if (!depositAmount) return;
dispatch(deposit(depositAmount, currency));
setDepositAmount("");
setCurrency("USD");
}
function handleWithdrawal() {
if (!withdrawalAmount) return;
dispatch(withdraw(withdrawalAmount));
setWithdrawalAmount("");
}
function handleRequestLoan() {
if (!loanAmount || !loanPurpose) return;
dispatch(requestLoan(loanAmount, loanPurpose));
setLoanAmount("");
setLoanPurpose("");
}
function handlePayLoan() {
dispatch(payLoan());
}
return (
<div>
<h2>Your account operations</h2>
<div className="inputs">
<div>
<label>Deposit</label>
<input
type="number"
value={depositAmount}
onChange={(e) => setDepositAmount(+e.target.value)}
/>
<select
value={currency}
onChange={(e) => setCurrency(e.target.value)}
>
<option value="USD">US Dollar</option>
<option value="EUR">Euro</option>
<option value="GBP">British Pound</option>
</select>
<button onClick={handleDeposit} disabled={isLoading}>
{isLoading ? "Converting..." : `Deposit ${depositAmount}`}
</button>
</div>
<div>
<label>Withdraw</label>
<input
type="number"
value={withdrawalAmount}
onChange={(e) => setWithdrawalAmount(+e.target.value)}
/>
<button onClick={handleWithdrawal}>
Withdraw {withdrawalAmount}
</button>
</div>
<div>
<label>Request loan</label>
<input
type="number"
value={loanAmount}
onChange={(e) => setLoanAmount(+e.target.value)}
placeholder="Loan amount"
/>
<input
value={loanPurpose}
onChange={(e) => setLoanPurpose(e.target.value)}
placeholder="Loan purpose"
/>
<button onClick={handleRequestLoan}>Request loan</button>
</div>
{currentLoan > 0 && (
<div>
<span>
Pay back ${currentLoan} ({currentLoanPurpose})
</span>
<button onClick={handlePayLoan}>Pay loan</button>
</div>
)}
</div>
</div>
);
}
export default AccountOperations;
React Router for
- New way of fetching data right inside React Router (v6.4+) that is worth exploring (“render-as-you-fetch” instead of “fetch-onrender”). Not really state management, as it doesn't persist state.
Performance Optimization
1. Child re render
- When parent componet has a state and a slow componet is child componet and when changing state in parent is re rendering the slow compone as well and if slow compone is not using that state it isolate then
- we have to pass that slow component as children prop in parent component so that children compone won't re render while changing state in parent component
function Counter({ children }) {
const [count, setCount] = useState(0);
return (
<div>
<h1>Slow counter?!?</h1>
<button onClick={() => setCount((c) => c + 1)}>Increase: {count}</button>
{children}
</div>
);
}
export default function Test() {
// const [count, setCount] = useState(0);
// return (
// <div>
// <h1>Slow counter?!?</h1>
// <button onClick={() => setCount((c) => c + 1)}>Increase: {count}</button>
// <SlowComponent />
// </div>
// );
return (
<div>
<h1>Slow counter?!?</h1>
<Counter>
<SlowComponent />
</Counter>
</div>
)
Memoization
The Memo function
- Memoizing the component
- its required when child componets prop is not changing frequently,
memofunction chache the result if prop is not changing , if prop is changin only then it will re rendered
const Archive = memo( component)
useMemo and useCALLBACK
- useMemo
- memo not working in object and function when we pass as en prop for that for object we have to use
useMemo and pass the dependency when this object has to re created else fetch from cache
const archiveOptions = useMemo(() => {
return {
show: false,
title: `Post archive in addition to ${posts.length} main posts`,
};
}, [posts.length]);
<Archive
archiveOptions={archiveOptions}
onAddPost={handleAddPost}
setIsFakeDark={setIsFakeDark}
/>
const value = useMemo(() => {
return {
posts: searchedPosts,
onAddPost: handleAddPost,
onClearPosts: handleClearPosts,
searchQuery,
setSearchQuery,
};
}, [searchedPosts, searchQuery]);
return (
// 2) PROVIDE VALUE TO CHILD COMPONENTS
<PostContext.Provider value={value}>{children}</PostContext.Provider>
);
- useCallback
- memo not working in object and function when we pass as an prop for that for function we have to use
useCallbackand pass the dependency when this function has to re created else fetch from cache
const handleAddPost = useCallback(function handleAddPost(post) {
setPosts((posts) => [post, ...posts]);
}, []);
<Archive
archiveOptions={archiveOptions}
onAddPost={handleAddPost}
setIsFakeDark={setIsFakeDark}
/>
Optimizing Bundle size
- Split bundle based on per page
const Homepage = lazy(() => import("./pages/Homepage"));
const Product = lazy(() => import("./pages/Product"));
const Pricing = lazy(() => import("./pages/Pricing"));
const Login = lazy(() => import("./pages/Login"));
const AppLayout = lazy(() => import("./pages/AppLayout"));
const PageNotFound = lazy(() => import("./pages/PageNotFound"));
- Suspense will suspend while js downloading from server
```js
<Suspense fallback={<SpinnerFullPage />}>
React Query
- setting the wild oasis project
- get the api key from supabase and put into supabase api variable
- app.js
const queryClient = new QueryClient({
defaultOptions: {
queries: {
// staleTime: 60 * 1000,
staleTime: 0,
},
},
});
<QueryClientProvider client={queryClient}>
<ReactQueryDevtools initialIsOpen={false} />
<GlobalStyles />
<BrowserRouter>
<Routes>
<Route element={<AppLayout />}>
<Route index element={<Navigate replace to="dashboard" />} />
<Route path="dashboard" element={<Dashboard />} />
<Route path="bookings" element={<Bookings />} />
<Route path="cabins" element={<Cabins />} />
<Route path="users" element={<Users />} />
<Route path="settings" element={<Settings />} />
<Route path="account" element={<Account />} />
</Route>
<Route path="login" element={<Login />} />
<Route path="*" element={<PageNotFound />} />
</Routes>
</BrowserRouter>
<Toaster
position="top-center"
gutter={12}
containerStyle={{ margin: "8px" }}
toastOptions={{
success: {
duration: 3000,
},
error: {
duration: 5000,
},
style: {
fontSize: "16px",
maxWidth: "500px",
padding: "16px 24px",
backgroundColor: "var(--color-grey-0)",
color: "var(--color-grey-700)",
},
}}
/>
</QueryClientProvider>
- apiCabins.js
export async function getCabins() {
const { data, error } = await supabase.from("cabins").select("*");
if (error) {
console.error(error);
throw new Error("Cabins could not be loaded");
}
return data;
}
- useCabins.js
import { useQuery } from "@tanstack/react-query";
import { getCabins } from "../../services/apiCabins";
export function useCabins() {
const {
isLoading,
data: cabins,
error,
} = useQuery({
queryKey: ["cabins"],
queryFn: getCabins,
});
return { isLoading, error, cabins };
}
- Cabins.js
import Spinner from "../../ui/Spinner";
import CabinRow from "./CabinRow";
import { useCabins } from "./useCabins";
import Table from "../../ui/Table";
import Menus from "../../ui/Menus";
import { useSearchParams } from "react-router-dom";
import Empty from "../../ui/Empty";
function CabinTable() {
const { isLoading, cabins } = useCabins();
const [searchParams] = useSearchParams();
if (isLoading) return <Spinner />;
if (!cabins.length) return <Empty resourceName="cabins" />;
// 1) FILTER
const filterValue = searchParams.get("discount") || "all";
let filteredCabins;
if (filterValue === "all") filteredCabins = cabins;
if (filterValue === "no-discount")
filteredCabins = cabins.filter((cabin) => cabin.discount === 0);
if (filterValue === "with-discount")
filteredCabins = cabins.filter((cabin) => cabin.discount > 0);
// 2) SORT
const sortBy = searchParams.get("sortBy") || "startDate-asc";
const [field, direction] = sortBy.split("-");
const modifier = direction === "asc" ? 1 : -1;
const sortedCabins = filteredCabins.sort(
(a, b) => (a[field] - b[field]) * modifier
);
return (
<Menus>
<Table columns="0.6fr 1.8fr 2.2fr 1fr 1fr 1fr">
<Table.Header>
<div></div>
<div>Cabin</div>
<div>Capacity</div>
<div>Price</div>
<div>Discount</div>
<div></div>
</Table.Header>
<Table.Body
// data={cabins}
// data={filteredCabins}
data={sortedCabins}
render={(cabin) => <CabinRow cabin={cabin} key={cabin.id} />}
/>
</Table>
</Menus>
);
}
export default CabinTable;
Thinking in react at 10000 Feet
UI to components
React Behind the scene
Practical Summary
Utility
Json server
- json server is creating a fake API using json file , we can use this for frontend development while backend is in development
- install json server
$ npm i json-server - Change in package.json file as below for json run command
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject",
"server": "json-server --watch data/questions.json --port 9000"
},
- put your json file in data folder questions.json
- start the json server
$ npm run server - use API using http://localhost:9000/questions
Reusability in react
Component Composition:
- This technique involves composing smaller, reusable components together to build larger components or user interfaces. By breaking down your UI into smaller, self-contained components, you can reuse them across different parts of your application. For example, you can create a Button component and reuse it in various places wherever a button is needed.
- Component Composition is a pattern where smaller, reusable components are composed together to build larger components or user interfaces. Each component remains independent and doesn't rely on specific knowledge or state from other components.
// Reusable components
function Header() {
return <h1>Header</h1>;
}
function Sidebar() {
return <div>Sidebar</div>;
}
function Content() {
return <div>Content</div>;
}
// Composition of components
function App() {
return (
<div>
<Header />
<div className="container">
<Sidebar />
<Content />
</div>
</div>
);
}
Props:
- Props allow you to pass data from a parent component to its child components. By passing different values to the props, you can reuse a component with varying data and behavior. For example, you can create a List component that receives an array of items as props, making it reusable for displaying different lists of items.
// Reusable List component
function List(props) {
return (
<ul>
{props.items.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
// Example usage
function App() {
const items = [
{ id: 1, name: "Item 1" },
{ id: 2, name: "Item 2" },
{ id: 3, name: "Item 3" },
];
return (
<div>
<h1>Props Example</h1>
<List items={items} />
</div>
);
}
Children Prop
- By using the children prop, you can create reusable components that can receive and render different child components or elements. This allows for flexible composition of components and promotes code reuse.
function ParentComponent({ children }) {
return (
<div>
<h1>Parent Component</h1>
{children}
<footer>Some footer content</footer>
</div>
);
}
<ParentComponent>
<ChildComponent1 />
<ChildComponent2 />
<div>Some text</div>
</ParentComponent>
Higher-Order Components (HOCs):
- HOCs are functions that take a component as input and return a new enhanced component. They allow you to add additional functionality or modify the behavior of a component without directly modifying its source code. HOCs can be used for cross-cutting concerns like authentication, data fetching, or logging. For example, you can create an withLogger HOC that wraps a component and adds logging capabilities to it.
- https://codesandbox.io/s/react-render-props-final-elme76?file=/src/HOC.js
// HOC that adds logging functionality to a component
function withLogger(WrappedComponent) {
return function WithLogger(props) {
useEffect(() => {
console.log(`Component ${WrappedComponent.name} mounted`);
return () => {
console.log(`Component ${WrappedComponent.name} unmounted`);
};
}, []);
return <WrappedComponent {...props} />;
};
}
// Example usage
function MyComponent(props) {
return <div>My Component</div>;
}
const EnhancedComponent = withLogger(MyComponent);
function App() {
return (
<div>
<h1>HOC Example</h1>
<EnhancedComponent />
</div>
);
}
Render Props:
- The Render Props pattern involves passing a function as a prop to a component, allowing the component to render the content provided by that function. It enables sharing logic or data between components by making the rendering behavior customizable. For example, you can create a Toggle component that uses a render prop to determine what to render when a button is toggled.
- https://codesandbox.io/s/react-render-props-final-elme76
function List({ title, items, render1 }) {
const [isOpen, setIsOpen] = useState(true);
const [isCollapsed, setIsCollapsed] = useState(false);
const displayItems = isCollapsed ? items.slice(0, 3) : items;
function toggleOpen() {
setIsOpen((isOpen) => !isOpen);
setIsCollapsed(false);
}
return (
<div className="list-container">
<div className="heading">
<h2>{title}</h2>
<button onClick={toggleOpen}>
{isOpen ? <span>∨</span> : <span>∧</span>}
</button>
</div>
{isOpen && <ul className="list">{displayItems.map(render1)}</ul>}
<button onClick={() => setIsCollapsed((isCollapsed) => !isCollapsed)}>
{isCollapsed ? `Show all ${items.length}` : "Show less"}
</button>
</div>
);
}
export default function App() {
return (
<div>
<h1>Render Props Demo</h1>
<div className="col-2">
<List
title="Products"
items={products}
render1={(product) => (
<ProductItem key={product.productName} product={product} />
)}
/>
<List
title="Companies"
items={companies}
render1={(company) => (
<CompanyItem
key={company.companyName}
company={company}
defaultVisibility={false}
/>
)}
/>
</div>
Custom Hook:
- By creating custom hooks, you can encapsulate complex logic and state management in a reusable manner
import { useState, useEffect } from 'react';
function useCustomHook(initialValue) {
const [count, setCount] = useState(initialValue);
useEffect(() => {
// Custom logic using useEffect
document.title = `Count: ${count}`;
}, [count]);
const increment = () => {
setCount(prevCount => prevCount + 1);
};
const decrement = () => {
setCount(prevCount => prevCount - 1);
};
return { count, increment, decrement };
}
export default useCustomHook;
import React from 'react';
import useCustomHook from './useCustomHook';
function MyComponent() {
const { count, increment, decrement } = useCustomHook(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
</div>
);
}
export default MyComponent;
Component Libraries:
- Utilizing component libraries or UI frameworks can provide pre-built, reusable components and styles for your application. Libraries like Material-UI, Ant Design, or Bootstrap offer a wide range of reusable components that you can leverage in your projects, saving development time and effort.
Compound Components:
- Compound Components is a pattern where a parent component wraps multiple child components and controls their behavior and state. The child components are designed to work together as a group and are tightly coupled with the parent component. They share a common context or state managed by the parent.
- https://codesandbox.io/s/react-compound-components-final-igzh7c
import { createContext, useContext, useState } from "react";
// 1. Create a context
const CounterContext = createContext();
// 2. Create parent component
function Counter({ children }) {
const [count, setCount] = useState(0);
const increase = () => setCount((c) => c + 1);
const decrease = () => setCount((c) => c - 1);
return (
<CounterContext.Provider value={{ count, increase, decrease }}>
<span>{children}</span>
</CounterContext.Provider>
);
}
// 3. Create child components to help implementing the common task
function Count() {
const { count } = useContext(CounterContext);
return <span>{count}</span>;
}
function Label({ children }) {
return <span>{children}</span>;
}
function Increase({ icon }) {
const { increase } = useContext(CounterContext);
return <button onClick={increase}>{icon}</button>;
}
function Decrease({ icon }) {
const { decrease } = useContext(CounterContext);
return <button onClick={decrease}>{icon}</button>;
}
// 4. Add child components as proeprties to parent component
Counter.Count = Count;
Counter.Label = Label;
Counter.Increase = Increase;
Counter.Decrease = Decrease;
export default Counter;
//-------------
import Counter from "./Counter";
import "./styles.css";
export default function App() {
return (
<div>
<h1>Compound Component Pattern</h1>
{/* <Counter
iconIncrease="+"
iconDecrease="-"
label="My NOT so flexible counter"
hideLabel={false}
hideIncrease={false}
hideDecrease={false}
positionCount="top"
/> */}
<Counter>
<Counter.Label>My super flexible counter</Counter.Label>
<Counter.Decrease icon="-" />
<Counter.Increase icon="+" />
<Counter.Count />
</Counter>
<div>
<Counter>
<Counter.Decrease icon="◀️" />
<div>
<Counter.Count />
</div>
<Counter.Increase icon="▶️" />
</Counter>
</div>
</div>
);
}
Libraries used in all projects
Amigose code FSP Vite
| Library | Description | Use |
|---|---|---|
| @chakra-ui/react | A component library that provides a set of accessible and customizable UI components for building React applications. | Used for creating visually appealing and responsive user interfaces with ready-to-use components and styling options. |
| @emotion/react | A library for writing CSS styles with JavaScript. | Used for styling React components using JavaScript instead of traditional CSS files. |
| @emotion/styled | A library that provides a styled component API for Emotion. | Used in combination with @emotion/react to create styled components with custom CSS styles. |
| axios | A promise-based HTTP client for making asynchronous HTTP requests. | Used for sending HTTP requests to a server and handling responses in React applications. |
| formik | A form management library that helps with handling form state, validation, and submission in React. | Used for building complex forms and managing form state and validation with ease. |
| framer-motion | A library for creating animations and interactive UI components in React. | Used for adding motion and animation effects to React components, creating engaging user interfaces. |
| jwt-decode | A library for decoding JSON Web Tokens (JWTs) in React. | Used for decoding and extracting information from JWTs in client-side React applications. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-dropzone | A React component that provides drag-and-drop file upload functionality. | Used for implementing file upload features, allowing users to drag and drop files for uploading. |
| react-icons | A library that provides a wide range of customizable icons for React applications. | Used for easily incorporating icons into React components, enhancing the visual design of the application. |
| react-router-dom | A library that provides routing capabilities for React applications. | Used for implementing client-side routing in React applications, enabling navigation between different views. |
| yup | A JavaScript schema validation library for defining and validating data schemas. | Used for creating and validating data schemas, often used in combination with form libraries like Formik. |
Jonas: https://fast-react-pizza-menu.netlify.app/
- https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/03-pizza-menu
| Library | Description | Use |
|---|---|---|
| @testing-library/jest-dom | A set of custom Jest matchers for asserting on DOM elements. | Used in combination with Jest for testing DOM-related assertions in React components. |
| @testing-library/react | A library that provides utilities for testing React components. | Used for writing tests and performing assertions on React components, such as rendering, interacting, and querying elements. |
| @testing-library/user-event | A library that provides simulated user events for testing. | Used to simulate user interactions, such as clicking, typing, and navigating, in tests for React components. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-scripts | A set of scripts and configurations for building and running React applications. | Used for various development tasks, such as starting the development server, bundling assets, and running tests. |
| web-vitals | A library for measuring and reporting web vital metrics, such as performance, accessibility, and user experience. | Used for monitoring and analyzing important metrics related to web performance and user experience. |
Jonas: https://travel-list-jonas.netlify.app/
- https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/05-travel-list
| Library | Description | Use |
|---|---|---|
| @testing-library/jest-dom | A set of custom Jest matchers for asserting on DOM elements. | Used in combination with Jest for testing DOM-related assertions in React components. |
| @testing-library/react | A library that provides utilities for testing React components. | Used for writing tests and performing assertions on React components, such as rendering, interacting, and querying elements. |
| @testing-library/user-event | A library that provides simulated user events for testing. | Used to simulate user interactions, such as clicking, typing, and navigating, in tests for React components. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-scripts | A set of scripts and configurations for building and running React applications. | Used for various development tasks, such as starting the development server, bundling assets, and running tests. |
| web-vitals | A library for measuring and reporting web vital metrics, such as performance, accessibility, and user experience. | Used for monitoring and analyzing important metrics related to web performance and user experience. |
Jonas: https://usepopcorn.netlify.app/
- https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/07-usepopcorn
| Library | Description | Use |
|---|---|---|
| @testing-library/jest-dom | A library that provides custom Jest matchers for asserting on DOM elements. | Used in combination with Jest for testing DOM-related assertions in React components. |
| @testing-library/react | A library that provides utilities for testing React components. | Used for writing tests and performing assertions on React components, such as rendering, interacting, and querying elements. |
| @testing-library/user-event | A library that provides simulated user events for testing. | Used to simulate user interactions, such as clicking, typing, and navigating, in tests for React components. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-scripts | A set of scripts and configurations for building and running React applications. | Used for various development tasks, such as starting the development server, bundling assets, and running tests. |
| web-vitals | A library for measuring and reporting web vital metrics, such as performance, accessibility, and user experience. | Used for monitoring and analyzing important metrics related to web performance and user experience. |
Jonas: https://the-react-quiz.netlify.app/
- https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/11-worldwise
| Library | Description | Use |
|---|---|---|
| json-server | A library that provides a simple way to set up a fake REST API server for development and testing purposes. | Used for mocking a backend API during development and testing of React applications. |
| leaflet | A popular open-source JavaScript library for interactive maps. | Used for integrating interactive maps and geospatial functionality into React applications. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-datepicker | A flexible and customizable date picker component for React. | Used for adding date selection functionality to forms or UI components in React applications. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-leaflet | A React library for integrating Leaflet maps into React applications. | Used for combining the functionality of Leaflet maps with React components and state management. |
| react-router-dom | A library that provides routing capabilities for React applications. | Used for implementing client-side routing in React applications, enabling navigation between different views. |
Jonas : 15-redux-intro
- https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/15-redux-intro
| Library | Description | Use |
|---|---|---|
| @reduxjs/toolkit | An official Redux library that provides utilities and abstractions for simplifying Redux setup and reducing boilerplate code. | Used for state management in React applications, offering a streamlined approach to Redux with built-in tools and features. |
| @testing-library/jest-dom | A library that provides custom Jest matchers for asserting on DOM elements. | Used in combination with Jest for testing DOM-related assertions in React components. |
| @testing-library/react | A library that provides utilities for testing React components. | Used for writing tests and performing assertions on React components, such as rendering, interacting, and querying elements. |
| @testing-library/user-event | A library that provides simulated user events for testing. | Used to simulate user interactions, such as clicking, typing, and navigating, in tests for React components. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-redux | A library that connects React components to the Redux store, enabling them to access the state and dispatch actions. | Used for integrating Redux with React components and managing the state of the application. |
| react-scripts | A set of scripts and configurations for building and running React applications. | Used for various development tasks, such as starting the development server, bundling assets, and running tests. |
| redux | A predictable state container for JavaScript applications. | Used for managing application state in a predictable and centralized manner. |
| redux-devtools-extension | A browser extension that enhances the Redux development experience by providing a visual representation of the Redux store and time-travel debugging capabilities. | Used during development to inspect and debug the Redux store and track state changes over time. |
| redux-thunk | A middleware for Redux that enables asynchronous and side-effect handling in Redux actions. | Used for dispatching asynchronous actions in Redux, such as making API requests or performing asynchronous operations. |
| web-vitals | A library for measuring and reporting web vital metrics, such as performance, accessibility, and user experience. | Used for monitoring and analyzing important metrics related to web performance and user experience. |
Jonas: https://fast-react-pizza.netlify.app/
- https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/16-fast-react-pizza
| Library | Description | Use |
|---|---|---|
| @reduxjs/toolkit | An official Redux library that provides utilities and abstractions for simplifying Redux setup and reducing boilerplate code. | Used for state management in React applications, offering a streamlined approach to Redux with built-in tools and features. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-redux | A library that connects React components to the Redux store, enabling them to access the state and dispatch actions. | Used for integrating Redux with React components and managing the state of the application. |
| react-router-dom | A library that provides routing capabilities for React applications. | Used for implementing client-side routing in React applications, enabling navigation between different views. |
| @types/react | TypeScript type declarations for the React library. | Used when developing React applications with TypeScript to provide type checking and autocompletion for React components. |
| @types/react-dom | TypeScript type declarations for the react-dom library. | Used when developing React applications with TypeScript to provide type checking and autocompletion for DOM-related operations. |
| @vitejs/plugin-react | A plugin for the Vite build tool that enables React support. | Used when building React applications with Vite, a fast build tool for modern web development. |
| autoprefixer | A tool that automatically adds vendor prefixes to CSS rules. | Used in the build process to ensure cross-browser compatibility by adding necessary CSS vendor prefixes. |
| eslint | A pluggable and configurable linter tool for identifying and reporting JavaScript code issues. | Used for static code analysis and enforcing coding standards in JavaScript and React projects. |
| eslint-config-react-app | A set of ESLint configurations for React applications created with Create React App. | Provides predefined ESLint rules and configurations optimized for Create React App projects. |
| postcss | A tool for transforming CSS with JavaScript plugins. | Used in the build process to transform and optimize CSS styles. |
| prettier | An opinionated code formatter that enforces consistent code style. | Used for automatic code formatting to maintain consistent code style across the project. |
| prettier-plugin-tailwindcss | A Prettier plugin for formatting Tailwind CSS classes. | Ensures consistent formatting of Tailwind CSS classes according to specified rules. |
| tailwindcss | A highly customizable CSS framework for building user interfaces. | Used for rapidly styling and building user interfaces in a responsive and efficient manner. |
| vite | A fast build tool and development server for modern web development. | Used for building and serving React applications with fast hot module replacement (HMR) support. |
| vite-plugin-eslint | A Vite plugin for integrating ESLint into the build process. | Enables ESLint to be used during the development server and build processes in Vite. |
| ### Jonas : https://the-wild-oasis.vercel.app/ | ||
| - https://github.com/jdbirla/JD_Front_End_Repo/tree/master/Jonas_Schmedtmann/React/ultimate-react-course-main/17-the-wild-oasis |
| Library | Description | Use |
|---|---|---|
| @supabase/supabase-js | A JavaScript client library for Supabase, an open-source alternative to Firebase that provides a real-time and secure backend-as-a-service (BaaS) platform. | Used for interacting with the Supabase backend and performing operations like querying, inserting, updating, and deleting data. |
| @tanstack/react-query | A powerful data fetching and caching library for React applications. | Used for managing data fetching, caching, and state synchronization with server APIs in React applications. |
| @tanstack/react-query-devtools | A developer tool that provides a UI to inspect and debug React Query data and state. | Used during development to monitor and debug React Query data fetching and caching behavior. |
| date-fns | A JavaScript library for manipulating and formatting dates. | Used for date parsing, formatting, and manipulation in React applications. |
| react | The core library for building React applications. | The foundation of React applications, used for creating components and managing their lifecycle. |
| react-dom | The package that provides DOM-specific methods for React. | Used for rendering React components into the browser's DOM. |
| react-error-boundary | A React component that catches JavaScript errors anywhere in its child component tree and displays a fallback UI. | Used to handle and display error boundaries in React applications, preventing uncaught errors from breaking the UI. |
| react-hook-form | A lightweight form library for React that provides an easy way to manage and validate form input state. | Used for handling form input state, validation, and submission in React applications. |
| react-hot-toast | A customizable toast notification library for React. | Used for displaying toast notifications or messages to users in React applications. |
| react-icons | A library that provides a collection of popular icons as React components. | Used for easily adding icons to React components and user interfaces. |
| react-router-dom | A library that provides routing capabilities for React applications. | Used for implementing client-side routing in React applications, enabling navigation between different views. |
| recharts | A charting library for React that allows you to create beautiful and responsive charts. | Used for creating interactive and visually appealing charts in React applications. |
| styled-components | A CSS-in-JS library that allows you to write CSS styles as JavaScript code within your React components. | Used for styling React components using tagged template literals and CSS syntax. |
React Quick Ref
ApiMarsFet
- chList
import { useState, useEffect } from "react";
export default function ApiMarsFetchList() {
const [mars, setMars] = useState([]);
useEffect(() => {
fetch("https://fakestoreapi.com/products/")
.then((res) => res.json())
.then((data) => setMars(data))
.catch((err) => console.log(err));
}, []);
mars.map((item, index) => console.log(item.id));
return (
<>
<ul>
{mars.map((item, index) => (
<li>{item.title}</li>
))}
</ul>
</>
);
}
ApiMarsFetchTable
import { useEffect, useState } from "react";
export function ApiMarsFetchTable() {
const [mars, setMars] = useState([]);
useEffect(() => {
fetch(
"https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?sol=1000&api_key=DEMO_KEY"
)
.then((res) => {
if (!res.ok) {
throw new Error(`mars not found : ${res.status}`);
}
return res.json();
})
.then((data) => setMars(data.photos))
.catch((err) => console.error(err))
.finally(() => {
console.log("finally");
});
}, []);
return (
<div className="container-fluid">
<h2>Mars Rover Photos</h2>
<table className="table table-hover">
<thead>
<tr>
<th>Photo Id</th>
<th>Preview</th>
<th>Camera</th>
<th>Rover</th>
</tr>
</thead>
<tbody>
{mars.map((item) => (
<tr key={item.id}>
<td>{item.id}</td>
<td>
<img src={item.img_src} width="100" height="100" />
</td>
<td>{item.camera.full_name}</td>
<td>{item.rover.name}</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
ApiUserAxiosList
import { useState, useEffect } from "react";
import axios from "axios";
export default function ApiUserAxiosList() {
const [users, setUsers] = useState([]);
useEffect(() => {
axios.get("https://reqres.in/api/users?page=1").then((response) => {
setUsers(response.data.data);
});
}, []);
return (
<div>
<ul>
{users.map((user) => (
<li key={user.id}>
{user.first_name} {user.last_name}
</li>
))}
</ul>
</div>
);
}
Classlifecycle
import React from "react";
export default class Header extends React.Component {
constructor(props) {
super(props);
this.state = { favoritecolor: "red" };
}
// static getDerivedStateFromProps(props, state) {
// return { favoritecolor: props.favcol };
// }
componentDidMount() {
setTimeout(() => {
this.setState({ favoritecolor: "yellow" });
}, 1000);
}
render() {
return <h1>My Favorite Color is {this.state.favoritecolor}</h1>;
}
}
ContextApi
import { useState, useContext } from "react";
import React from "react";
const CountContext = React.createContext();
const Counter = () => {
const { count, increase, decrease } = useContext(CountContext);
return (
<h2>
<button className="btn btn-danger" onClick={decrease}>
Decrement
</button>
<span className="count">{count}</span>
<button className="btn btn-success" onClick={increase}>
Increment
</button>
</h2>
);
};
// App.js
const ContextApi = () => {
const [count, setCount] = useState(0);
const increase = () => {
setCount(count + 1);
};
const decrease = () => {
setCount(count - 1);
};
return (
<div>
<CountContext.Provider value={{ count, increase, decrease }}>
<Counter />
</CountContext.Provider>
</div>
);
};
export default ContextApi;
CounterReducer
import { useReducer } from "react";
let initialState1 = { count: 0 };
function reducer1(state, action) {
switch (action.type) {
case "add":
return { count: state.count + 1 };
case "remove":
return { count: state.count - 1 };
case "reset":
return { count: 0 };
default:
throw new Error("not a valide case");
}
}
export function CounterApp() {
const [state1, dispatch1] = useReducer(reducer1, initialState1);
function AddClick() {
dispatch1({ type: "add" });
}
function RemoveClick() {
dispatch1({ type: "remove" });
}
function reset() {
dispatch1({ type: "reset" });
}
return (
<div className="container-fluid">
{/* <p>Cat Itmes [{state1.count}]</p> */}
<h2>Count: {state1.count}</h2>
<button className="btn btn-warning m-2" onClick={AddClick}>
Add
</button>
<button className="btn btn-dark m-2" onClick={RemoveClick}>
Delete
</button>
<button className="btn btn-danger m-2" onClick={reset}>
Reset
</button>
</div>
);
}
CounterUseState
import React, { useState } from "react";
function CounterUseState() {
const [count, setCount] = useState(0);
function increment() {
setCount((prevCount) => prevCount + 1);
}
function decrement() {
setCount((prevCount) => prevCount - 1);
}
function reset() {
setCount(0);
}
return (
<div>
<h2>Count: {count}</h2>
<button className="btn btn-warning m-2" onClick={increment}>
Increment
</button>
<button className="btn btn-dark m-2" onClick={decrement}>
Decrement
</button>
<button className="btn btn-danger m-2" onClick={reset}>
Reset
</button>
</div>
);
}
export default CounterUseState;
JsWithDifferentUIElement
var product = {
Name: "Samsung TV",
Price: 46500.44,
Stock: true,
questions: ["small", "medium", "big"],
};
const questions = [
{
question: "Which is the most popular JavaScript framework?",
options: ["Angular", "React", "Svelte", "Vue"],
correctOption: 1,
points: 10,
},
{
question: "Which company invented React?",
options: ["Google", "Apple", "Netflix", "Facebook"],
correctOption: 3,
points: 10,
},
{
question: "What's the fundamental building block of React apps?",
options: ["Components", "Blocks", "Elements", "Effects"],
correctOption: 0,
points: 10,
},
];
export default function JsWithDifferentUIElement() {
return (
<div>
<div className="container-fluid">
<h3 className="text-success">
-----------------Product Object Data List:Start-----------------
</h3>
<h5>Product Details</h5>
<dl>
<dt>Name</dt>
<dd>{product.Name}</dd>
<dd>
<input type="text" defaultValue={product.Name} />
</dd>
<dt>Price</dt>
<dd>{product.Price}</dd>
<dt>Stock</dt>
<dd>{product.Stock == true ? "Available" : "Out of Stock"}</dd>
<dd>
<input type="checkbox" defaultChecked={product.Stock} /> Available
</dd>
<dt>questions</dt>
{product.questions.map((que, index) => (
<dd key={index}>{que}</dd>
))}
</dl>
<h3 className="text-success">
-----------------Product Object Data List:End-----------------
</h3>
</div>
<div className="container-fluid mt-2">
<div>
<h3 className="text-success">
-----------------questions Array Table:Start-----------------
</h3>
<table className="table table-hover table-dark">
<thead>
<tr>
<th>Questions</th>
</tr>
</thead>
<tbody>
{questions.map((que, index) => (
<tr key={index}>
<td>{que.question}</td>
<td>{que.options.join(",")}</td>
<td>{que.correctOption}</td>
<td>{que.points}</td>
</tr>
))}
</tbody>
</table>
<h3 className="text-success">
-----------------questions Array Table:End-----------------
</h3>
</div>
<h3 className="text-success">
-----------------questions Array button:Start-----------------
</h3>
<div className="w-25">
{questions.map((que, index) => (
<div key={index}>
{que.options.map((opt, index) => (
<button
key={index}
className="btn btn-link mb-2 w-100"
>{`${index} -> ${opt}`}</button>
))}
</div>
))}
</div>
<h3 className="text-success">
-----------------questions Array button:End-----------------
</h3>
<div>
<h2>Toolbar</h2>
<div className="btn-toolbar bg-danger mb-2">
<div className="btn-group">
{questions.map((que, index) => (
<button className="btn btn-danger">{que.question}</button>
))}
</div>
</div>
</div>
<div className="row">
<div className="col">
<ol>
{questions.map((que, index) => (
<li key={index}>{que.question}</li>
))}
</ol>
</div>
<div className="col">
<select>
{questions.map((que, index) => (
<option key={index}>{que.question}</option>
))}
</select>
</div>
<div className="col">
<ul className="list-unstyled">
{questions.map((que, index) => (
<li key={index}>
<input type="checkbox" /> {que.question}{" "}
</li>
))}
</ul>
</div>
</div>
</div>
</div>
);
}
PassDataFromChildToParent
import React, { useState } from "react";
export function ParentComponent() {
const [parentData, setParentData] = useState("");
const [valueFromChild, setValueFromChild] = useState(0);
function handleChildDataChange(data, valueFromChild) {
setParentData(data);
setValueFromChild(valueFromChild);
}
return (
<div>
<h2>Parent Data: {parentData}</h2>
<h2>valueFromChild Data: {valueFromChild}</h2>
<ChildComponent
onChildDataChange={handleChildDataChange}
counterValue={valueFromChild}
/>
</div>
);
}
function ChildComponent(props) {
const [childData, setChildData] = useState("");
let childCounterValue = props.counterValue;
function handleInputChange(event) {
setChildData(event.target.value);
props.onChildDataChange(event.target.value, childCounterValue + 1);
}
return (
<div>
<input type="text" value={childData} onChange={handleInputChange} />
</div>
);
}