React Hooks

Hooks allows components to access state and other functionality. Those are simply javascript functions which differ from react functional components. It improves the performance of react application.Hooks are secure, reusable, readable and flexible.

Things to remember:

We have to import hooks before using it

Hooks can call only inside the react component

The below are the main list of built-in hooks available in react

1. useState

useState allows the application to track the state of a component. useState needs a variable to hold the state and a function to update the state.

import { useState } from 'react';

export default function Profile() {
  const [profileName, setprofileName] = useState(null);

  function handleProfile() {
    setprofileName(profileName ? null : "George");
  }

  return (
   <div>
    <button onClick={handleProfile}>
      {profileName ? `Clear My Name` : "Check My Name" }
    </button>
   <div>{profileName ? `My Name is ${profileName}` : "" }</div>
   </div>
  );
}

In the above example const [profileName, setprofileName] = useState(null); profileName is the state variable whose initial value is null and setprofileName is the function to update the value of profileName.

2. useReducer

useReducer is the same as useState.The difference is we can use reducer function to add the custom logic.

import { useReducer } from 'react';

function  handleProfile(state, action) {
  if (action.type === 'clear') {
    return {
      profileName: null
    };
  } else {
    return {
      profileName: "George"
    };
  }
}
export default  function Profile() {
  const [state, dispatch] = useReducer(handleProfile, { profileName: null });
  return (
    <>
      <button onClick={() => {
        dispatch({ type: 'clear' })
      }}>
      Clear My Name
      </button>
      <button onClick={() => {
        dispatch({ type: 'check' })
      }}>
        Check My Name
      </button>
      <div>{state.profileName ? `My Name is ${state.profileName}` : "" }</div>
    </>
  );
}

In the above example  const [state, dispatch] = useReducer(handleProfile, { profileName: null }); state is holding current state, dispatch is a function to update the state, handleProfile is reducer function to add custom logics, the initial value can be passed as second param of useReducer. There is an optional third parameter. This will be a function to calculate the initial values.

3. useEffect

useEffect is allowing the react to connect with an external system. If we want to do something on rendering or update some data based on changing dependency value, we can use useEffect.

import { useState, useEffect } from "react";
import React from 'react';

export default function Profile() {
  const [profileName, setProfileName] = useState(null);
  const [updateCount, setUpdateCount] = useState(0);
  useEffect(() => {
    setProfileName('George Updated ' + updateCount + 'Times')
  }, [updateCount])
  function handleProfile() {
    setUpdateCount(updateCount + 1)
  }
  return (
   <div>
    <button onClick={handleProfile}>
      {profileName ? "Clear My Name" : "Check My Profile Status" }
    </button>
   <div>{profileName ?  profileName  : "" }</div>
   </div>
  );
}

useEffect has two arguments. First one is the function for doing logic based on the second dependency argument.

Normally useEffect will run on every render.

useEffect(() => {
})

If we want to run the useEffect only on first render please use empty dependency array

useEffect(() => {
}, [])

If we want to run the useEffect only on first render and at the time dependency change, please use some dependency as second argument.

useEffect(() => {
}, [updateCount])

4. useRef

useRef is used to track the value that is not needed for rendering. It can be used to refer to an HTML input element. useRef returns an object which has current property that will hold the value of ref.

export default function Profile() {
    const inputTextValue = useRef("")
    const [profile, setProfile] = useState("")


 function showProfile() {
         setProfile(inputTextValue.current.value)
  }

    function clearProfile() {
         setProfile("")
  }

  return (
   <div>
       <input type="text"  ref={inputTextValue} id={'profile'} />
       <div>Current Name is {profile}</div>
       <button onClick={showProfile}>
      Check Input
    </button>
       <button onClick={clearProfile}>
      Clear Input
    </button>
   </div>
  );
}

5. useContext

useContext is used to maintain global state. It can be used to pass the value from parent component to child components.


 import { useState, createContext, useContext} from "react";
import React from 'react';

const UserContext = createContext();

export default function App(props) {
 const [user, setUser] = useState("George");
  return (
    <UserContext.Provider value={user}>
      <h1>{`My Name is ${user}!`}</h1>
      <Profile />
    </UserContext.Provider>
  );
}

export function Profile() {
    const user = useContext(UserContext)
  return (
   <div>
       {`Hello again ${user}`}
   </div>
  );
}

6. useMemo

useMemo is used to cache the return value of a function. If we need to run a function on each render, we can avoid extensive calculation and cache the results for better performance.

import { useState, useMemo } from "react";
import React from 'react';

export function App(props) {
  return (
    <div className='App'>
     {Profile()}
      <h1>Hello React.</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

export default function Profile() {
  const [updateCount, setUpdateCount] = useState(0);

  function handleProfile() {
    setUpdateCount(updateCount + 1)
  }

    function clearProfile() {
    setUpdateCount(updateCount)
  }

    function checkProfileName () {
        return 'George Updated ' + updateCount + 'Times'
    }

    const profileName = useMemo(() => checkProfileName (), [updateCount]);

  return (
   <div>
    <button onClick={handleProfile}>
      Count More
    </button>
       <button onClick={clearProfile}>No Update</button>
   <div>{profileName ?  profileName  : "" }</div>
   </div>
  );
}

7. useCallback

Unlike useMemo which is caching function response, useCallback will cache the function itself for the later use. This hook is very useful to prevent the re rendering when the components props are changed.

import { useState, useMemo, useCallback } from "react";
import React from 'react';

export function App(props) {
  return (
    <div className='App'>
     {Profile()}
      <h1>Hello React.</h1>
      <h2>Start editing to see some magic happen!</h2>
    </div>
  );
}

export default function Profile() {
  const [updateCount, setUpdateCount] = useState(0);
 const [updateCall, setUpdateCall] = useState(0);

  function handleProfile() {
    setUpdateCount(updateCount + 1)
  }

    function handleCallBack() {
    setUpdateCall(updateCall + 1)
  }

    function clearProfile() {
    setUpdateCall(updateCount)
  }

    const checkProfileName = useCallback(() => {
        return 'George Updated ' + updateCount + 'Times'
    }, [updateCall])
    

    const profileName = useMemo(() => checkProfileName(), [updateCount]);

  return (
   <div>
    <button onClick={handleProfile}>
      Memo
    </button>
       <button onClick={handleCallBack}>
      Call back
    </button>
       <button onClick={clearProfile}>No Update</button>
   <div>{profileName ?  profileName  : "" }</div>
   </div>
  );
}