{"id":611,"date":"2024-06-13T02:12:30","date_gmt":"2024-06-13T02:12:30","guid":{"rendered":"https:\/\/wp.techrity.org\/WordPress\/?p=611"},"modified":"2024-07-04T03:29:41","modified_gmt":"2024-07-04T03:29:41","slug":"creating-custom-react-hooks","status":"publish","type":"post","link":"https:\/\/wp.techrity.org\/WordPress\/2024\/06\/13\/creating-custom-react-hooks\/","title":{"rendered":"Creating Custom React Hooks &#8211; Oyinkansola Odunsi"},"content":{"rendered":"\n<p>If you\u2019re not new to React, you probably know about or have used hooks like useState and useEffect before. However, do you know that you can create your own hook? Yes, you heard that right! And this is what this article is about.&nbsp;<\/p>\n\n\n\n<p>Also, if you\u2019re a newbie to JavaScript library, I\u2019ve got you covered! I\u2019ll bring you up to speed on the existing React hooks, and help you understand how to create yours. Let\u2019s dive right in.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">WHAT ARE REACT HOOKS?<\/h2>\n\n\n\n<p>The React library is commonly used because it\u2019s easy to handle. One of this library\u2019s excellent functionalities is React hooks. In simple terms, React hooks are JavaScript functions that allow you to access state and other React features without writing a class.&nbsp;<\/p>\n\n\n\n<p>These functions can also used to isolate the reusable parts of functional components. Additionally, they are identified by the word <strong>use<\/strong>, followed by the superpowers they possess like <strong>DebugValue<\/strong>, <strong>Effect<\/strong>, <strong>Callback<\/strong>, and <strong>LayoutEffect<\/strong>.&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">THE EXISTING REACT HOOKS<\/h2>\n\n\n\n<p>The latest React version (version 18) has 15 built-in hooks that you can use. The most commonly used hooks are useState, useEffect, and useContext. Here is a list and a summary of all the existing React hooks:<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><strong>useCallback<\/strong>: Returns a memoized (stored to avoid repeated computation) callback function so that the child component that depends on the function will not re-render unnecessarily. The function will only be recreated if one of its dependencies changes.&nbsp;&nbsp;<\/li><li><strong>useContext<\/strong>: After creating a context, useContext allows you to use a value in the context further down in your functional components. So, you don\u2019t have to manually pass props down your component tree.&nbsp;<\/li><li><strong>useDebugValue<\/strong>: Helps you label the output of your custom hooks so you can easily understand their state and monitor their behaviour in React DevTools.<\/li><li><strong>useDeferredValue<\/strong>: Useful for prioritizing the responsiveness of your user interface by deferring long-running operations that might affect the performance of your application.<\/li><li><strong>useEffect<\/strong>: This hook handles side effects in your functional components. Side effects include fetching data, setting up event listeners, and DOM manipulation.&nbsp;<\/li><li><strong>useId<\/strong>: Helps you generate unique IDs across your React application.<\/li><li><strong>useImperativeHandle<\/strong>: Allows you to specify the properties of a component that should be exposed when using refs.<\/li><li><strong>useInsertionEffect<\/strong>: This makes it easy for you to execute a function after a component has been added to the DOM.<\/li><li><strong>useLayoutEffec<\/strong>t: It works similarly to useEffect, but it\u2019s synchronous. You can use it to make changes on your DOM immediately when it&#8217;s updated, and before the browser displays content on a user\u2019s screen.&nbsp;<\/li><li><strong>useMemo<\/strong>: It is used to memoize the result of expensive computations to avoid unnecessary recalculations.<\/li><li><strong>useReducer<\/strong>: Instead of using useState you can use useReducer to handle more complex state logic within a functional component.<\/li><li><strong>useRef<\/strong>: Helps you create mutable references that you can access across multiple renders of a functional component.&nbsp;<\/li><li><strong>useState<\/strong>: Allows you to manage the state within a functional component.<\/li><li><strong>useSyncExternalStore<\/strong>: This hook allows you to read and subscribe to an external data store.<\/li><li><strong>useTransition<\/strong>: Helps you manage asynchronous updates to a React application\u2019s UI.<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">WHY DO WE NEED CUSTOM HOOKS?<\/h2>\n\n\n\n<p>Don\u2019t get me wrong, this article is not to say that the in-build React hooks are not sufficient. React has all these powerful hooks that will serve you well. Nonetheless, I can\u2019t deny the reality that custom hooks can greatly improve the readability and overall quality of your code.<\/p>\n\n\n\n<p>Let\u2019s open up this fact a little bit by highlighting why you might need a custom hook:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>It makes logic reusable.<\/li><li>It allows you to use other hooks provided by React.<\/li><li>You can easily separate your logic from your UI.<\/li><li>You can break down complex stateful logic into simple chunks of code that are easy to maintain.<\/li><li>You can test specific parts of your stateful logic because custom hooks can be debugged in isolation.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">TIPS FOR CREATING CUSTOM REACT HOOKS<\/h2>\n\n\n\n<p>Here are some tips to keep in mind to ensure your custom hooks are flexible, reusable, and easy to understand.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Follow the naming convention by starting with <strong>use<\/strong>.<\/li><li>Repeated\/reusable logic within your components should be your custom hooks candidates.<\/li><li>Feel free to use the built-in React hooks where necessary.<\/li><li>Make sure a hook is focused on one responsibility instead of multiple functions.<\/li><li>Your hooks should have value or functions that components can use.<\/li><li>Ensure your hooks can accept parameters so you can easily customize their behaviour.<\/li><li>Test your hooks in different scenarios to ensure they are performing as expected. You can use tools like Jest and\/or the React Testing Library.<\/li><li>Document your hook and succinctly explain its function.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">CREATING YOUR FIRST CUSTOM HOOK<\/h2>\n\n\n\n<p><strong>Step 1: Define Your Hook<\/strong><\/p>\n\n\n\n<p>Let\u2019s create a custom React hook that would allow our application toggle between light and dark mode (our reusable logic). To begin, we create a JavaScript file to define our hook.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { useState, useEffect } from 'react';\nfunction useDarkMode() {\n  const &#91;isDarkMode, setIsDarkMode] = useState(false);\n  useEffect(() =&gt; {\n    const body = document.body;\n    if (isDarkMode) {\n      body.classList.add('dark-mode');\n    } else {\n      body.classList.remove('dark-mode');\n    }\n  }, &#91;isDarkMode]);\nconst toggleDarkMode = () =&gt; {\n    setIsDarkMode(prevMode =&gt; !prevMode);\n  };\n  return &#91;isDarkMode, toggleDarkMode]:\n}\nexport default useDarkMode;\n<\/code><\/pre>\n\n\n\n<p><strong>Step 2: Use Your Custom Hook<\/strong><\/p>\n\n\n\n<p>Now, we can use our custom hook in our React component.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React from 'react';\nimport useDarkMode from '.\/useDarkMode';\nfunction App() {\n  const &#91;isDarkMode, toggleDarkMode] = useDarkMode();\n  return (\n    &lt;div className=\"App\"&gt;\n      &lt;button onClick={toggleDarkMode}&gt;\n        Toggle Dark Mode\n      &lt;\/button&gt;\n      &lt;div className={isDarkMode ? 'dark-mode' : 'light-mode'}&gt;\n        {isDarkMode ? 'Dark Mode' : 'Light Mode'}\n      &lt;\/div&gt;\n    &lt;\/div&gt;\n  );\n}\nexport default App;\n<\/code><\/pre>\n\n\n\n<p><strong>Step 3: Test Your Hoo<\/strong>k<\/p>\n\n\n\n<p>To carry out the test, you\u2019ll have to install the Jest and the React Testing Library&nbsp;using:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>npm install --save-dev @testing-library\/react @testing-library\/jest-dom jest\n<\/code><\/pre>\n\n\n\n<p>Then, we\u2019ll create a test file for our custom hook. Let\u2019s call it <strong>useDarkMode.test.js<\/strong>.<\/p>\n\n\n\n<p>We\u2019ll proceed to use the <strong>renderHook<\/strong> and <strong>act<\/strong> utilities in our React Testing Library to test our hook.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { renderHook, act } from '@testing-library\/react-hooks';\nimport useDarkMode from '.\/useDarkMode';\n\n\ndescribe('useDarkMode', () =&gt; {\n  test('should toggle dark mode correctly', () =&gt; {\n    const { result } = renderHook(() =&gt; useDarkMode());\n    \/\/ Initial state should be light mode (isDarkMode: false)\n    expect(result.current&#91;0]).toBe(false);\n    expect(document.body.classList.contains('dark-mode')).toBe(false);\n    \/\/ Toggle to dark mode\n    act(() =&gt; {\n      result.current&#91;1](); \/\/ toggleDarkMode\n    });\n    expect(result.current&#91;0]).toBe(true);\n    expect(document.body.classList.contains('dark-mode')).toBe(true);\n    \/\/ Toggle back to light mode\n    act(() =&gt; {\n      result.current&#91;1](); \/\/ toggleDarkMode\n    });\n    expect(result.current&#91;0]).toBe(false);\n    expect(document.body.classList.contains('dark-mode')).toBe(false);\n  });\n});\n<\/code><\/pre>\n\n\n\n<p>Next, add Jest to your <strong>package.json<\/strong> file as follows, then run npm test to confirm that the useDarkMode hook is running as expected:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\"scripts\": {\n  \"test\": \"jest\"\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Step 4: Document Your Custom Hook<\/strong><\/p>\n\n\n\n<p>Document how your custom hook works and include details like its parameters and return values.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">CREATING A DATA FETCHING CUSTOM HOOK<\/h2>\n\n\n\n<p>Now that you have an idea of how to create a custom React hook, let\u2019s build another common custom hook (a data fetching hook) to further reinforce our knowledge. Shall we?<\/p>\n\n\n\n<p><strong>Step 1<\/strong>: <strong>Create the hook.<\/strong> <\/p>\n\n\n\n<p>We\u2019ll call it <strong>useFetch.js<\/strong>. This custom hook is commonly used to allow several components to fetch data from an API.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { useState, useEffect } from 'react';\n\n\nfunction useFetch(url) {\n  const &#91;data, setData] = useState(null);\n  const &#91;loading, setLoading] = useState(true);\n  const &#91;error, setError] = useState(null);\n\n\n  useEffect(() =&gt; {\n    const fetchData = async () =&gt; {\n      setLoading(true);\n      try {\n        const response = await fetch(url);\n        if (!response.ok) {\n          throw new Error('Network response was not ok');\n        }\n        const data = await response.json();\n        setData(data);\n      } catch (error) {\n        setError(error);\n  } finally {\n        setLoading(false);\n      }\n    };\n    fetchData();\n  }, &#91;url]);\n\n\n  return { data, loading, error };\n}\nexport default useFetch;\n<\/code><\/pre>\n\n\n\n<p><strong>Step 2<\/strong>: <strong>Use your new hook in a component.<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import React from 'react';\nimport useFetch from '.\/useFetch';\nfunction App() {\n  const { data, loading, error } = useFetch('https:\/\/api.google.com\/data');\n  if (loading) return &lt;div&gt;Loading...&lt;\/div&gt;;\n  if (error) return &lt;div&gt;Error: {error.message}&lt;\/div&gt;;\n  return (\n    &lt;div&gt;\n      &lt;h1&gt;Data:&lt;\/h1&gt;\n      &lt;pre&gt;{JSON.stringify(data, null, 2)}&lt;\/pre&gt;\n    &lt;\/div&gt;\n  );\n}\nexport default App;\n<\/code><\/pre>\n\n\n\n<p><strong>Step 3<\/strong>: <strong>Test and document your custom hook.<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import { renderHook } from '@testing-library\/react-hooks';\nimport useFetch from '.\/useFetch';\n\/\/ Mock the fetch function\nglobal.fetch = jest.fn(() =&gt;\n  Promise.resolve({\n    ok: true,\n    json: () =&gt; Promise.resolve({ data: 'mocked data' }),\n  })\n);\ndescribe('useFetch', () =&gt; {\n  afterEach(() =&gt; {\n    fetch.mockClear();\n  });\n  it('should return data after fetch', async () =&gt; {\n    const { result, waitForNextUpdate } = renderHook(() =&gt; useFetch('https:\/\/api.example.com\/data'));\n    expect(result.current.loading).toBe(true);\n    await waitForNextUpdate();\n    expect(result.current.loading).toBe(false);\n    expect(result.current.data).toEqual({ data: 'mocked data' });\n    expect(result.current.error).toBe(null);\n  });\n  it('should return an error if fetch fails', async () =&gt; {\n    fetch.mockImplementationOnce(() =&gt;\n      Promise.reject(new Error('Fetch failed'))\n    );\n    const { result, waitForNextUpdate } = renderHook(() =&gt; useFetch('https:\/\/api.example.com\/data'));\n    await waitForNextUpdate();\n    expect(result.current.loading).toBe(false);\n    expect(result.current.error).toBe('Fetch failed');\n    expect(result.current.data).toBe(null);\n  });\n});\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">GET STARTED TODAY<\/h2>\n\n\n\n<p>By leveraging the power of custom hooks, you\u2019ll be able to write simple,&nbsp; maintainable and readable codes. And trust me, once you get started, you are locked in by the ease these functions bring to your programming journey.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>If you\u2019re not new to React, you probably know about or have used hooks like useState and useEffect before. However, do you know that you can create your own hook? Yes, you heard that right! And this is what this article is about.&nbsp; Also, if you\u2019re a newbie to JavaScript library, I\u2019ve got you covered! [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":612,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[18,78,21,19],"tags":[50],"ppma_author":[124],"class_list":["post-611","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-general","category-how-tos","category-software","category-tech","tag-tech"],"authors":[{"term_id":124,"user_id":1,"is_guest":0,"slug":"rity_admin","display_name":"Owanate Amachree","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/2310c3b487ccb4ab80e12e38ea6bf6c0f4d8dba8aed074f7de39bda1e44be671?s=96&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/posts\/611","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/comments?post=611"}],"version-history":[{"count":3,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/posts\/611\/revisions"}],"predecessor-version":[{"id":616,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/posts\/611\/revisions\/616"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/media\/612"}],"wp:attachment":[{"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/media?parent=611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/categories?post=611"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/tags?post=611"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/wp.techrity.org\/WordPress\/wp-json\/wp\/v2\/ppma_author?post=611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}