Shubham Bansal

What is React Hooks

By Shubham Bansal

Last updated cal_iconMarch 14, 2023

React hooks are a type of function that allows the users to hook into react state and life-cycle features from function components. React provides built-in hooks like useState, useEffect, useReducer, useRef, use Callback, useContext, useMemo and we can also create your own custom hooks.

React hooks are available from react version 16.8. Before the introduction of hooks, state can be maintained only in-class components, not in functional components. After the introduction of hooks, state can be maintained in functional components too.

The idea of using hooks makes it possible to create full-fledged functional components, while using all the React features. This allows us to make everything easier, unlike classes.

The main problems which were solved by release of hooks in React 16.8:

  • Wrapper ****Hell
  • Classes
  • Side effect

In ReactJS, the most difficult thing is to reuse logic in stateful components. Before the appearance of React hooks, there was no way to reuse the logic of behavior to the component, for example, to connect it to the store.

The following examples make it clear why hooks are useful.

Using Classes :

import React, { Component } from ‘react’;

class App extends Component {

constructor(props) {

super(props);

this.state = {

isButtonClicked: false,

}

this.handleClick = this.handleClick.bind(this);

}

handleClick() {

this.setState((prevState) => ({

isButtonClicked: !prevState.isButtonClicked,

}));

}

Using Hooks :

import React, { useState } from ‘react’;

const App = () => {

const [isButtonClicked, setIsButtonClickedStatus] = useState(false);

return (

<button

onClick={() => setIsButtonClickedStatus(!isButtonClicked)}

>

{isButtonClicked ? ‘Clicked’ : ‘Click me, please’}

</button>

);

};

From this, we can understand that hooks work similarly to such concepts as a state.

Rules of Using React Hooks

Hooks are just JavaScript functions, but they require two specific rules:

  • Hooks should be performed at the very top of the function hierarchy which means that the users should not call hooks in conditions and loops, otherwise the reaction cannot guarantee the execution order of hooks.
  • We should call hooks only in React functions or functional components or call hooks from custom hooks.

What is Custom Hooks

Custom Hook is a JavaScript function which we create by ourselves, when we want to share logic between other JavaScript functions. It allows you to reuse some piece of code in several parts of your app.

Advantages and disadvantages

  • Improving Readability of Component Tree

The “useContext” hook has been a blessing for greatly improving the readability of JSX as it allows context values to be read outside of JSX. This was also previously possible in class components by using the static “contextType” property but is even cleaner with “useContext”.

Aside from the code being easier to read it is also much easier to read the component tree in the React dev tools when debugging. The value of this really adds up for components which previously used multiple nested contexts.

  • Encapsulating Side Effects

With class components the setup and teardown of side effects were split across multiple lifecycle methods like the event listeners could be added in “componentDidMount” and later removed in “componentWillUnmount”. If any component has multiple side effects this could lead to less readable code with a related logic split across several incohesive lifecycle methods.

But the “use Effect” solves this problem by handling both the setup and teardown of side effects. It does so by allowing the effect function to return a function to teardown the effect. It is evident from the below example:

useEffect(() => {

window.addEventListener(“resize”, resizeHandler);

return () =>

window.removeEventListener(“resize”, resizeHandler);

}, []);

  • Composable and Reusable Logic

Custom hooks are considerably a great mechanism for sharing logic across various components. A custom hook is simply a function which uses one or more React hooks and it can be called within a functional component, just like a standard hook.

A nice example is a custom hook for tracking the result of a media query and returning this state to the component. It demonstrates how hooks can be combined. It uses “useEffect” to set up an event listener to track changes in whether a media query is matched or not. It also uses “useState” to store this state and return the result to the calling component.

function use MatchMedia(mediaQuery) {

const [matches, setMatches] = useState(window.matchMedia(mediaQuery).matches);

useEffect(() => {

const updateMatches = event => {

setMatches(event.matches);

};

const mediaQueryList = window.matchMedia(mediaQuery);

setMatches(mediaQueryList.matches);

mediaQueryList.addListener(updateMatches);

return () => mediaQueryList.removeListener(updateMatches);

}, [mediaQuery]);

return matches;

}

  • hooks are easier to work with and to test (as separated functions from React components*) and make the code look cleaner, easier to read — a related logic can be tightly coupled in a custom hook. Check below visualization of differences between standard stateful component and a one using hooks:
  • By separated functions I mean writing a logic as your own hooks that are just functions that return values or functions used for accessing and manipulating state with use of standard React hooks. We still have to test them through a mock React component but I think it’s more readable and easier than testing HOCs:

import React, { useState } from ‘react’;

export const useTextField = name => {

const [value, setValue] = useState(”);

const onChange = event => {

setValue(event.target.value);

};

return {

name,

value,

onChange,

placeholder: name,

};

};

const InputDemoWithHooks = () => {

const nameField = useTextField(‘name’);

return <input type=”text” {…nameField} />;

};

export default InputDemoWithHooks;

And tests for the hook:

import React from ‘react’;

import { mount } from ‘enzyme’;

const TestHook = ({ callback }) => {

callback();

return null;

};

export const testHook = (callback) => {

mount(<TestHook callback={callback} />);

};

// tests

import { act } from ‘react-dom/test-utils’;

import { testHook } from ‘./testUtils’;

import { useTextField } from ‘../InputDemoWithHooks’;

let nameField;

beforeEach(() => {

testHook(() => {

nameField = useTextField(‘name’);

});

});

describe(‘useTextField’, () => {

test(‘should have an onChange function’, () => {

expect(nameField.onChange).toBeInstanceOf(Function);

});

test(‘should have correct name’, () => {

expect(nameField.name).toBe(‘name’);

});

test(‘should update the value when onChange is called’, () => {

act(() => {

nameField.onChange({ target: { value: ‘nitin’ } });

});

expect(nameField.value).toBe(‘nitin’);

});

});

  • code that uses hooks is more readable and have less LOC (lines of code), let’s look on a standard class component example:

// example class component that we will rewrite as function component

class Form extends React.Component {

constructor(props) {

super(props);

this.saveToDraft = debounce(500, this.saveToDraft);

};

state = {

// Fields values

fields: {},

// Draft saving meta

draft: {

isSaving: false,

lastSaved: null,

},

};

saveToDraft = (data) => {

if (this.state.isSaving) {

return;

}

this.setState({

isSaving: true,

});

makeSomeAPICall().then(() => {

this.setState({

isSaving: false,

lastSaved: new Date(),

})

});

}

componentDidUpdate(prevProps, prevState) {

if (!shallowEqual(prevState.fields, this.state.fields)) {

this.saveToDraft(this.state.fields);

}

}

render() {

return (

<form>

{/* Draft saving meta render */}

{/* Inputs render */}

</form>

);

};

}

And the same component as above rewritten as function component

// the above class component rewritten as function component,

const Form = () => {

// Our state

const [fields, setFields] = useState({});

const [draftIsSaving, setDraftIsSaving] = useState(false);

const [draftLastSaved, setDraftLastSaved] = useState(false);

useEffect(() => {

const id = setTimeout(() => {

if (draftIsSaving) {

return;

}

setDraftIsSaving(true);

makeSomeAPICall().then(() => {

setDraftIsSaving(false);

setDraftLastSaved(new Date());

});

}, 500);

return () => clearTimeout(id);

}, [fields]);

return (

<form>

{/* Draft saving meta render */}

{/* Inputs render */}

</form>

);

}

  • thanks to hooks it’s easy to make code more reusable / composable (also they don’t create another element in DOM like HOCs do) — with HOCs we are separating unrelated state logic into different functions and injecting them into the main component as props, although with Hooks, we can solve this just like HOCs but without a wrapper hell. Let’s compare below example:

example reusable logic for liking posts on a feed implemented as HOC,

And the same logic rewritten with use of hooks:

componentDidMount rewritten for React Hooks,

  • hooks are going to work better with future React optimizations (like ahead of time compilation and components folding) — components folding might be possible in future — what means dead code elimination at compile time (less JS code to download, less to execute)
  • Even now, minification of functions in JavaScript is much better than minification of JavaScript classes. It’s not possible for example to minify method names of JS classes as every method can be either private or public, so we don’t know when it’s used outside the class. Less code to download, process and execute has a positive impact for the end user. Check comparison:

comparison between minification of class component and function component that uses hooks.

  • Hooks show the real nature of React which is functional, using classes make developers easier to make mistakes and use React anti-patterns. In my career I encountered examples where people with object-oriented programming backgrounds tended to extend class components… that were hard times for debugging
  • hooks are very convenient to re-use stateful logic, this is one of their selling points. But this is not applicable when an app is built using some state management library and stateful logic doesn’t live in React components. So for an app on which I work in its current state hooks are mostly for readability and to make it future-proof because for local logic we use MobX stores

React Hooks vs older approaches for reusable logic

  • Read code examples and think of differences in implementing logic between in a Class Component:

  • and as Mixins (deprecated):

  • and as HOCs (Higher Order Components):

  • and as Render Props:

  • and as Hooks:

Mixins are deprecated API. HOCs disadvantage is they create additional DOM elements so when you use few HOCs, then you will see your component nested in few DOM elements. Render props if nested are creating similar structures as “callback hell” in the past. Hooks have no disadvantages of using multiple custom hooks on a single component.

When and How to Use

When we want to share the logic between other components, we can extract it to a separate function. According to official documents, the custom hook has to:

  • start with the key word use
  • call other hooks

Because custom hook is a JS function, the Rules of Hooks apply to it as well. Those are:

  • Never call Hooks from inside a loop, condition or nested function
  • Hooks should sit at the top-level of your component
  • Only call Hooks from React functional components
  • Never call a Hook from a regular function
  • Hooks can call other Hooks

Disadvantages

  • It’s hard to reuse stateful logic between components.
  • Complex components become hard to understand.

Limitations

  • Only call hooks at the top Level.
  • Only Call hooks from React function components.

Name:- npm i stack-ui-hooks

  1. useArray
  2. useSet
  3. useMap
  4. useList
  5. useBoolean
  6. useNumber
  7. useCheckbox
  8. useActive
  9. useAsync
  10. useBind
  11. useDidMount
  12. useDidUpdate
  13. useClickOutside
  14. useDelay
  15. useDocumentReady
  16. useFocus
  17. useGoogleAnalytics
  18. useImage
  19. useInput
  20. useLogger
  21. useOnclick
  22. usePageLoad
  23. usePersist
  24. usePrevious
  25. usePersist
  26. useScript
  27. useWindowSize
  28. UseActive
  29. UseAsync
  30. UseBind
  31. UseCheckbox
  32. UseCounter
  33. useDidMount
  34. useDidUpdate
  35. useEqualEffect
  36. useFetch
  37. useField
  38. useFocus
  39. useGlobalState
  40. useHover
  41. useMergeState
  42. useNestedBind
  43. useNestedState
  44. useStateCallback
  45. useToggle
  46. useTouch
  47. useUndo
  48. useWillUnmount
  49. useCounter
  50. useFocus
  51. useInput
  52. useInterval
  53. useLifecycleHooks
  54. useMergeState
  55. useOnMount
  56. useOnUnmount
  57. usePrevius
  58. useTimeout
  59. useAsync
  60. useAsyncFn
  61. useAsyncRetry
  62. useAudio
  63. useBatery
  64. useBeforeUnload
  65. useClickAway
  66. useCookie
  67. useCopyToClipboard
  68. useCounter
  69. useCss
  70. useCustomCompareEffect
  71. useDebounce
  72. useDeepCompareEffect
  73. useDefault
  74. useDrop
  75. useDropArea
  76. useEffectOnce
  77. useEnsuredForwardedRef
  78. useError
  79. useEvent
  80. useFavicon
  81. useFirstMountState
  82. useFullscreen
  83. useGeolocation
  84. useGetSet
  85. useGetSetState
  86. useHarmonicInterval
  87. useHash
  88. useHoverDirty
  89. useIdle
  90. useIntersection
  91. useInterval
  92. useIsomorhicLayoutEffect
  93. useKey
  94. useKeyboardJs
  95. useLatest
  96. useLifecycle
  97. useLocalStorage
  98. useLocation
  99. useLockBodyScroll
  100. useLogger
  101. useLongPress
  102. useMeasure
  103. useMeasureDirty
  104. useMedia
  105. useMediaDevices
  106. useMediatedState
  107. useMethod
  108. useMotion
  109. useMount
  110. useMountedState
  111. useMouse
  112. useMouseWheel
  113. useMultiStateValidator
  114. useNetworkState
  115. useObservable
  116. useOrientation
  117. usePageleave
  118. usePermission
  119. usePrevious
  120. usePreviousDistinct
  121. usePromise
  122. useQueue
  123. useRaf
  124. useRafLoop
  125. useRafState
  126. useRenderCount
  127. useScratch
  128. useScroll
  129. useScrollbarWidth
  130. useScrolling
  131. useSearchParam
  132. useSessionStorage
  133. useSetState
  134. useShallowCompareEffect
  135. useSize
  136. useSlider
  137. useSpring
  138. useStartTyping
  139. useStateList
  140. useStateValidator
  141. useStateWithHistory
  142. useThrottle
  143. useThrottleFn
  144. useTitle
  145. useTween
  146. useUnmount
  147. useUnmountPromise
  148. useUpdate
  149. useUpdateEffect
  150. useUpsert
  151. useVibrate
  152. useVedio
  153. useWait
  154. useWindowScroll
  155. useWindowSize
  156. useAdjustColor
  157. useDarkMode
  158. useEventListner
  159. useDimensions
  160. useFullScreen
  161. useGeoLocation
  162. useLsClient
  163. useKeyPress
  164. useMultiKeyPress
  165. useNotification
  166. useOnClickOutside
  167. useOnlineStatus
  168. usePrevious
  169. usePrint
  170. useQueryParams
  171. useSpeech
  172. useSpeechRecognition
  173. useSpeechSynthesis
  174. useWorker

Website—– like stackui

Lang use —– typescript

Npm package launch

Presentation

Code — private github

Project create reference :-

https://www.smashingmagazine.com/2020/05/typescript-modern-react-projects-webpack-babel/

Get In Touch

How Can We Help ?

We make your product happen. Our dynamic, robust and scalable solutions help you drive value at the greatest speed in the market

We specialize in full-stack software & web app development with a key focus on JavaScript, Kubernetes and Microservices
Your path to drive 360° value starts from here
Enhance your market & geographic reach by partnering with NodeXperts