Skip to content

React

Debugging

Double Rendering

  • In the Development environment components two times render because of React.StrictMode but not in production

React Developer Tools

image

Redux Devtool

  • Add chrome extension Redux devtool
  • install npm I redux-devtools-extension
  • wrap inside composeWithDevTools image

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 image image

React Query Dev Tool

Install @tanstack/react-query-devtools

<QueryClientProvider client={queryClient}>
      <ReactQueryDevtools initialIsOpen={false} />

image


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

image - {} 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"));

image

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

image


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

image

Passing element (jsx) as prop

  • it alternative to children's prop image

State

react-state-decision drawio

Always update state using callback

 if (step < 3) {
      setStep((s) => s + 1);  // Correct way
      // setStep(step + 1); //incorrect way
    }

image

State uplifting

image image image

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

image

Hooks

useEffect

  • Sideeffect must be run in evenhandler or useEffect not in render logic
  • useEffect always executes after browser paint
  • image
  • Every state variable and prop used inside the effect MUST be included in the dependency array
  • image image
  • 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]
  );

image image image image

useRef

  • How not to select DOM element in react image image image

custom Hooks

image

useReducer

image image

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

image image

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);
      }}
    >
      &larr; Back
    </Button>
  );
}

Context API

image

  • Context api mostly using by Custom Provider
  • Create seprate context file
  • Create custome componet like below PostProvider create 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 useContext so that all subscribe can direcly use this custom hook and no required for useContext hook
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

image image image

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 image image
  • 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 image
  • 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

image

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

image

The Memo function

  • Memoizing the component image
  • its required when child componets prop is not changing frequently,memo function 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

image image image - 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 useCallback and 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

image image - 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

image

  • setting the wild oasis project
  • get the api key from supabase and put into supabase api variable image
  • 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

image Untitled-2023-06-15-0819

UI to components

image image image image


React Behind the scene

react-behind-scene Untitled-2023-06-15-0819

image image image image image image image image

Practical Summary

image image image


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

Reusability drawio

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>&or;</span> : <span>&and;</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>
  );
}