Skip to content

๐ŸชThis repository will represent my concept about react-hooks. Well based on the React docs there are 10 hooks are exist in react library. So when we have to use which hooks & knowledge about how the react-hooks actually work is important to feel the actual beauty of React.

Notifications You must be signed in to change notification settings

tanvir1017/react-hooks

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

16 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

REACT HOOKS ๐Ÿช + vit svg

React hooks thumbnail for README.md

Here is the importance links ๐Ÿ”—

Start button image

๐Ÿชด The available React hooks๐Ÿ“ƒ

    1. useSTate most frequently use
    2. useCallback
    3. useContext
    4. useDebugValue
    5. useDeferredValue
    6. useEffect
    7. useId
    8. useImperativeHandle
    9. useInsertionEffect
    10. useLayoutEffect
    11. useMemo
    12. useReducer
    13. useRef
    14. useSyncExternalStore
    15. useTransition

๐Ÿ‘‰1๏ธโƒฃ useCallback

โš“ cache the function between re-renders.useCallback function let's you cache the function between many re-renders

const [userInput, setUserInput] = useState("");
const [result, setResult] = useState(0);
const [num] = useState(5);
const [num1] = useState(4);

const sum = useCallback(() => num + num1, [num1, num]);
useEffect(() => {
  console.log(`New sum result is as usual : ${sum()}`);

  // ? Endless loop! For react is so smart, it can detect the same value and not changed anything because of value is same and prevent the loop. So what's going on hereโ“We are updating the state by setResult(sum())-(because of sum return a permeative value). When the state change react re-render component. When component re-render() useEffect called and useEffect is looking for [sum] changes and inside of the useEffect we are again change the state by putting sum() inside of setResult(). Again state change when state change react re-render components after re-render useEffect called and blah blah. It could be endless loop like this. But react can detect that value is not changing that's why it's not happing.๐Ÿš€

  setResult(sum());
}, [sum]);
const [result, setResult] = useState(0);
const [num] = useState(5);
const [num1] = useState(4);
// without useCallback
const buildArray = () => [num, num1];

// with useCallback. ๐Ÿš€ Now it's have the referential equality. It will memoized function before the function gives new value or return new value
const buildArray = useCallback(() => [num, num1], [num, num1]);
useEffect(() => {
  console.log(`New array: ${buildArray()}`);

  // ? Endless loop! For react is so smart, it can detect the same value and not changed anything because of value is same and prevent the loop. So what's going on hereโ“We are updating the state by setResult(sum())-(because of sum return a permeative value). When the state change react re-render component. When component re-render() useEffect called and useEffect is looking for [sum] changes and inside of the useEffect we are again change the state by putting sum() inside of setResult(). Again state change when state change react re-render components after re-render useEffect called and blah blah. It could be endless loop like this. But react can detect that value is not changing that's why it's not happing.๐Ÿš€
  setResult(sum());

  // ? What if? if you don't use useCallback in โš“ buildArray() function. BuildArray function returning a new array and we are set the returned buildArray function array to the result state. So it's going to be an endless rendering loop.
  setResult(buildArray());
}, []);

๐Ÿชด Endless reandering loop look like this ๐Ÿซค

endless loop without using useCallback and returning a referential value

๐Ÿ‘‰2๏ธโƒฃ useMemo

โš“ cache the expensive calculation or value between re-renders. useMemo function let's you cache the expensive function value or expensive calculation between many re-renders.

๐Ÿชด Use case Or references

  • Skipping the expensive recalculations
  • Skipping the rendering of components
  • Memoizing the dependency of another hook
  • Memoizing function
import React, { useEffect, useState } from "react";

const fibo = (n) => {
  return n <= 1 ? n : fibo(n - 1) + fibo(n - 2);
};
export default function Memo() {
  const [useNumber, setUseNumber] = useState(0);
  // ?๐Ÿ”– reference from line number 116 - 126. ๐Ÿคฏ  Why this states input will slowโ“Cause from react useState we know that when we change any of state in react app the app will render for every changes. So whenever we type a new word or input it set the input to the randomInput state. โš“ When it's setting the value app will render โš“ When render the app the fiboNumber variable call the fibonacci function and regenerate the value again. Also we know that fibonacci function is so expensive about performance. So if you give the long value above the  30 the function will goes to expensive in performance. And lag your app instantly.
  const [randomInput, setRandomInput] = useState("");

  const fiboNumber = fibo(useNumber);
  useEffect(() => {
    console.log("fibonacci : ", fiboNumber);
    console.log("random input are taken");
  }, [fiboNumber]);
  return (
    <>
      <hr />
      <h1>useMemo ๐Ÿ“</h1>
      <div>
        <label htmlFor="fibonacci-number">Fibonacci number : </label>
        <input
          style={{ padding: ".45rem 1.5rem" }}
          type="text"
          value={useNumber}
          onChange={(e) => setUseNumber(e.target.value)}
        />
        <p style={{ textAlign: "center" }}>
          Fibonacci number is: {fiboNumber | "--"}
        </p>
      </div>
      <div>
        <label htmlFor="fibonacci-number">Random Input : </label>
        <input
          style={{ padding: ".45rem 1.5rem" }}
          type="text"
          value={randomInput}
          onChange={(e) => setRandomInput(e.target.value)}
        />
        <p style={{ textAlign: "center" }}>
          Given random input is : {randomInput}
        </p>
      </div>
    </>
  );
}

๐Ÿชด so what can we do here with useMemo ๐Ÿค”

// ? What exactly going on here๐Ÿค”โ“  So in this line below we use react hooks called useMemo. Which is memoized the value off fibo function and it will render the application when useNumber dependency will change. So here useMemo element your application lag and do not effect on your application's other actions
const fiboNumber = useMemo(() => fibo(useNumber), [useNumber]);

๐Ÿชด Difference view of the useCallback & useMemo๐Ÿ‘€

// ? So what can we doโ“ If the expensive function(fibo) is inside the components we can use react hooks called useCallback as we explained it before. We know clearly know that useCallback memoized the function & useMemo memoized the function value. So if you use useCallback hooks when components has some update or state change it should be memoized the expensive function(fibo) & it knows that function has know changes or no new return stuff. It will keep the function as it is and eliminated the laggings form the app
export default function Memo() {
  const fibo = useCallback((n) => {
    return n <= 1 ? n : fibo(n - 1) + fibo(n - 2);
  }, []);

  // ? What exactly going on here๐Ÿค”โ“ So in this line below we use react hooks called useMemo. Which is memoized the value off fibo function and it will render the application when useNumber dependency will change. So here useMemo element your application lag and do not effect on your application's other actions
  const fiboNumber = useMemo(() => fibo(useNumber), [useNumber, fibo]);
}

useRef

โš“ This hook let's reference you the value thatโ€™s not needed for rendering.

Syntax

import { useRef } from "react";
const inputRef = useRef(initialValue);

when we have to use it ๐Ÿ‘ˆ

  1. A value frequently changes and it nots require to render the component's. Like an input field which is changes when you type something or delete something by pressing backspace.
  2. We can use react hook useRef Instead of using the state, when the state set every value when client pressing the key, it will re-render the app in every press. useRef will reference the value and doesn't re-render the components.
  3. โš ๏ธ Also we can manipulate vanilla js DOM. So it's not the right way to manipulate dom in react by vanilla js. React came for building single page application by thinking in react-full way. So ti's not the good practice to manipulate dom using useRef

useReducer

โš“ useReducer let's you add reducer to you component.

And we also know reducer function reduce your work and give you more flexibility. Instead of using a lot of state ! you can handle all of your functional components state in one reducer function

Let's bring an example by code: ๐Ÿ˜Ž

import { useReducer } from "react";

const reducerFunc = (state, action) => {
  switch (action.type) {
    case "INCREMENT": {
      return { ...state, count: state.count + 1 };
    }
    case "DECREMENT": {
      return { ...state, count: state.count - 1 };
    }
    case "R-INPUT": {
      return { ...state, inputText: action.payload };
    }
    case "TG-COLOR": {
      return { ...state, color: !state.color };
    }
    default:
      throw new Error("hey there is problem with your action");
  }
};
export default function Reducer() {
  const [state, dispatch] = useReducer(reducerFunc, {
    count: 0,
    inputText: "",
    color: false,
  });

  const [count, setCount] = useState(0);
  const [inputText, setInputText] = useState("");
  const [color, setColor] = useState(false);

Or see the example by a picture, *which is also like this code was mentioned before *๐Ÿฅฑ

useReducer picture example

useLayoutEffect

โš“ useLayoutEffect works before browser repaints the screen.

Everything in useEffect and useLayoutEffect is same its syntax, dependency everything. But differences between both them is:

  • useEffect is asynchronous and useLayoutEffect is synchronous.
  • useEffect is fired after rendered the page or browser paints the screen & useLayoutEffect fired the side effect before browser repaints the screen.

Side Effect โ“

Side effect is something will change inside of the useEffect or useLayoutEffect if any of the state or something else like dependency (which is given to the hooks [dependency]) change on the page.

  • โš ๏ธ useEffect is mostly used instead of useLayoutEffect because useLayoutEffect is hurt the performances. 99% case you will use useEffect 1% case you will use useLayoutEffect, And the 1% is when you want to not show the changes to the client after render or browser repaints.

useImperativeHandle

โš“ useImperativeHandle lets you give access to the child components to the inside of parent components

. In useImperativeHandle Hooks we need to use two more hooks with useImperativeHandle Hooks.

  1. useRef for keep reference the child component function or action
  2. forwardRef for forwarding the child components to the parents when we export the functional components
  3. useImperativeHandle This hooks use inside the child components and everything inside of the hooks are available on parent hooks by ref.current

when we use this hooks and call the child components from parents we have to add useRef, because this ref will keep the reference from child. Also the child component will take two parameter

  1. props must be in parameter,
  2. ref which will take the useRef from parents

๐Ÿ‘‰ let's bring an example:

Child components

function ModalChild(props, ref) {
  console.log("ref from child", ref);
  const [modalState, setModalState] = useState(false);
  const obje = {
    name: "Tanvir Hossain",
    age: 20,
  };
  useImperativeHandle(ref, () => ({
    modalState,
    obje,
    openModal: () => setModalState(true),
  }));

  if (!modalState) return null;
  console.log("child component rendered");
  return <>jsx</>;
}

export default forwardRef(ModalChild);

Parent's components

import ModalChild from "./ModalChild";

export default function ImperativeHandle() {
  const modalRef = useRef();

  const handleModalOpenRef = () => {
    modalRef.current.openModal();
  };

  console.log("parent rendered");
  return (
    <>
      <ModalChild ref={modalRef} />
    </>
  );
}

useDebugValue

โš“ useDebugValue lets you send some informative data to the React DEV__TOOLS, to keep your current status of your code

useTransition

โš“ `useTransition . It will lets you update the state without blocking the Ui. It does not take any parameters and returns an array with exactly two items.

  1. isPending

  2. startTransition function

    The isPending flag tells you whether there is a pending function.Another one (startTransition) function that let's you update the state without ui blocking as a transition`

This hooks you may use frequently. โš ๏ธ On more thing is wit will renders many. When you see something (state) is sluggish you app or block the ui then you can use it for instant update the state and show the current status by isPending items

๐Ÿ‘‰ Let's see an example:

const Transitions = () => {
  const [counter, setCounter] = useState(0);
  const [items, setItems] = useState([]);
  const [isPending, startTransition] = useTransition();
  const handleToDoTransitions = () => {
    setCounter((prev) => prev + 1);

    startTransition(() => {
      const itemsArray = Array(20000)
        .fill(1)
        .map((el, i) => counter + 20000 - i);
      setItems(itemsArray);
    });
  };
  return (
    <div>
      <button onClick={handleToDoTransitions}>{counter}</button>
      {isPending ? <p>loading....</p> : null}
      <ul>
        {items.map((el) => (
          <li key={el}>{el}</li>
        ))}
      </ul>
    </div>
  );
};

useDeferredValue

โš“ useDeferredValue. This react hook look like work as debounce do. But it has difference. It will keep the data until the re-render happened and state change. Means? Let us a state which will keep our onChange value from an input when we change something in input it will update the state with input value instantly and re-render the component.

const [query, setQuery] = useState("")
//  render return
//  So when we change something it will re-render the components and update the state every time
<input type="text" value={query} onChange={(e) => setQuery(e.target.value)}  />

๐Ÿš€ Instead if we use useDeferredValue

const [query, setQuery] = useState("")
// useDeferredValue
const deferredValue = useDeferredValue(query)
const [isPending, startTransition] = useTransition()

useEffect(() => {
  startTransition( () => {
    console.log(deferredValue)
  })
}, [deferredValue])
//  render return
//  So when we change something it will re-render the components and update the state every time
<input type="text" value={query} onChange={(e) => setQuery(e.target.value)}  />

So what's going on actually ๐Ÿ˜Ÿ?

Let me explain the hooks and behavior of useDeferredValue Hooks. So here we are setting the default useDeferredValue value what we will have from the input. So according to the behavior of the onChange it will keep track your every changes, so now when we change something it will set the input value to the setQuery function. When it set the value to the function the component will re-render and update the state.In particular, React will first re-render without updating the deferred value, and then try to re-render with the newly received value in background.

About

๐ŸชThis repository will represent my concept about react-hooks. Well based on the React docs there are 10 hooks are exist in react library. So when we have to use which hooks & knowledge about how the react-hooks actually work is important to feel the actual beauty of React.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published