Learn React Hooks

Ishika Gupta
Jul 9, 2020 · 8 min read

Hooks are a new addition in React 16.8. They allow us to use React features without writing a class based components. There are 3 Basic Hooks and other hooks are either variants of the basic ones , or only needed for specific edge cases.

In this article we cover almost all hooks.

  • useState
  • useEffect
  • useContext
  • useReducer
  • useMemo, React.memo
  • useCallback
  • useRef, callbackRef, forwardRef
  • useImperativeHandle
  • useLayoutEffect
  • useDebugValue

BASIC HOOKS

1. useState

const [state, setState] = useState(initialState);

The setState function is used to update the state. It accepts a new state value and enqueues a re-render of the component.If your update function returns the exact same value as the current state, the subsequent re render will be skipped completely.The initialState argument is the state used during the initial render. In subsequent renders, it is disregarded (fig 1.2).

fig 1. 2 useState

2. useEffect

useEffect(didUpdate);    useEffect(()=>{},[dependencies])

If we write the useEffect without square brackets then the function passed to useEffect will run on every render.

initial rendering happens before mounting. Rendering returns the elements which are supposed to be mounted in the DOM. Mounting a react component means the actual addition of the DOM elements created by the react component into the browser DOM for the first time.The main difference between mounting and rendering is that mounting happens once, but rendering can happen any number of times.

  • Function Passed to useEffect will run on every re render if no dependency is passed (fig-2.1).
2.1 useEffect without dependency
  • componentDidMount and componentWillUnmount If dependency is an empty array then it will behave like componentDidMount and componentWillUnmount (fig- 2.2).
2.2 useEffect mount and unmount
  • if we only want to re render the component in change of any state or prop then pass the state or prop in dependency array (fig 2.3).
  • componentDidUpdate sometimes we want the function to run only on update not on mount then we can write like fig 2.3. Here Did Update will only log when ‘click’ change its value. it will not print in its first render.
2.3 useEffect did update

if we pass object , array and function in dependency then the function passed to useEffect will run on every render. Object reference will change on every re render.

3. useContext

const value = useContext(MyContext)
const ContextName = React.createCotext(initialvalue);

When the nearest <MyContext.Provider> above the component updates, this Hook will trigger a re render with the latest context value. Here theme object is passed as a context. we can access its value without manually passing the props at every level.

fig 3.1 useContext

Other Hooks

4. useReducer

const [state, dispatch] = useReducer(reducer, initialArg, init);
(state, action) => newState

Why useReducer, If useState can also update the State

when there is complex state logic that involves multiple sub-values or when the next state depends on the previous one and also to optimise the performance that has deep updates because we can pass dispatch down instead of callbacks. Dispatch reference will not create on every re render but callback reference will create in each re render.

fig 4.1 useReducer
  • Use useState whenever you manage a JS primitive
  • Use useReducer whenever you manage an object or array

sometimes we want to manage the state at top-level but want to trigger state changes somewhere deep down in our component tree. It’s possible to pass both the updater function from useState or the dispatch function from useReducer as a props in component tree but using context may be a better alternative to avoid prop drilling (passing props through each component level). In that case, having one dispatch function with different action types and payloads may be a better option than using multiple updater functions from useState that must be passed down individually. The dispatch function can be passed down once with useContext Hook.

fig 5.0 optimisation

React.memo , useMemo and useCallback hooks are used for optimisation. Their motive is to prevent unnecessary renders.

React.memo similar to pureComponent in class components and used for a performance boost in some cases by memoizing the result. This means that React will skip re rendering the component, and reuse the last rendered result.

fig 5.1 React.memo

In fig 5.1 we update the value of count1 and component will re render but one thing you notice , <Count> does not use ‘click’ state but <Count> still re render because React Says that if parent re render then its child also re render until we used any optimisation. In order to prevent the re rendering of <Count> we can use React.memo. It checks for props changes and will skip re rendering the component if props value are same. In this example <Count> will not re render if we use React.memo.

If we pass object, array or function as a prop then React.memo will not work because their new reference will create on each re render and React.memo uses reference equality to prevent unnecessary renders.

5. useCallback and useMemo

const memoizedCallback = useCallback(
() => {
doSomething(a, b);
},
[a, b],
)
const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
fig 5.2 useCallback and useMemo

In fig 5.2 you can see that the main difference is , React.useMemo will call the Function and return its result while React.useCallback will return the function without calling it .

fig 5.3 useCallback

In fig 5.3 Function is passed as a prop in <Actions> and on changing the state of ‘check’ <Actions> will re render . In this case we can not use React.memo because new reference of function will generate on each re render. we want that the function reference will not create until some dependency will change.If function is pass in useCallback then the function reference will not generate. Function reference will only generate if any state or props passed in the dependency array will change.

useMemo returns memoized value.Imagine that you’ve got a function that synchronously calculates a value which is computationally expensive to calculate.With useMemo, we never have to calculate the same value twice .we can use same value again until dependencies array’s values will change. If our dependencies array is empty, there is no possibility of memoization and it will compute a new value on every render.

6. useRef

const refContainer = useRef(initialValue);
fig 6.1 question

Here question is if createRef exist then why there is need for useRef.

createRef will return a new ref on every render.Every invocation of createRef will generate a new object. It is perfect for a class component’s constructor.while useRef will return the same ref each time.

fig 6.2 useRef

In fig 6.2 on click we set the current property of ref and component will not re render that means useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render.

We can use useCallbackRef , the callback ref will be invoked when a component mounts and be set to null when the component un mounts.

fig 6.3 useCallbackRef

In fig 6.3 ‘ref set’ will log when <input> added to DOM and will log again when <input> tag unmount.

useImperativeHandle before this we need to know about useForwardRef.

can we pass ref as a prop?

No, ref is a reserved word like key. We can’t pass it like a prop. Ref forwarding is a technique for automatically passing a ref through a component to one of its children. In fig 7.1 we create a ref in <Hello> and pass it to <RefCom> using forwardRef.

fig 7.1 forwardRef

7. useImperativeHandle

fig 7.2 useImperativeHandle

In fig 7.2 we can use extra function log() using useImperativeHandle i.e It customises the instance value that is exposed to parent components when using ref.

8. useLayoutEffect

Difference between useEffect and useLayoutEffect?

Only differs in when it is fired.The function passed to useEffect fires after layout and paint, during a deferred event.The function passed to useLayoutEffect fires before paint like componentDidMount.

9. useDebugValue

useDebugValue(value, [optional formatting function]);
fig 9.1 useDebugValue

In fig 9.1 second is not correct way because formattedDate value will always calculate.useDebugValue function is only called if the Hooks are inspected. It receives the debug value as a parameter and should return a formatted display value.

Last words

Thanks for Reading !!

Gradeup Engineering

Sahi Prep Hai Toh Life Set Hai!

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store