{"id":13459932,"url":"https://github.com/sergeyleschev/react-custom-hooks","last_synced_at":"2025-03-24T18:31:29.548Z","repository":{"id":179740133,"uuid":"661037209","full_name":"sergeyleschev/react-custom-hooks","owner":"sergeyleschev","description":"React Custom Hooks @ S.Leschev: useArray useAsync useClickOutside useCookie useCopyToClipboard useDarkMode useDebounce useDebugInformation useDeepCompareEffect useEffectOnce useEventListener useFetch useGeolocation useHover useLongPress useMediaQuery useOnlineStatus useOnScreen usePrevious useRenderCount useScript etc.","archived":false,"fork":false,"pushed_at":"2024-02-24T05:43:12.000Z","size":292,"stargazers_count":533,"open_issues_count":0,"forks_count":111,"subscribers_count":15,"default_branch":"main","last_synced_at":"2024-08-01T10:19:51.914Z","etag":null,"topics":["frontend","hooks","hooks-and-redux","hooks-and-resolvers","hooks-api","hooks-api-react","hooks-async","hooks-folder","hooks-library","hooks-props-and-state","hookstate","javascript","react","react-components","react-hooks","reactjs","reactjs-components","typescript","ui","web-development"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sergeyleschev.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2023-07-01T15:37:11.000Z","updated_at":"2024-08-01T10:19:51.915Z","dependencies_parsed_at":"2024-01-21T08:41:48.168Z","dependency_job_id":null,"html_url":"https://github.com/sergeyleschev/react-custom-hooks","commit_stats":null,"previous_names":["sergeyleschev/react-custom-hooks"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeyleschev%2Freact-custom-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeyleschev%2Freact-custom-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeyleschev%2Freact-custom-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sergeyleschev%2Freact-custom-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sergeyleschev","download_url":"https://codeload.github.com/sergeyleschev/react-custom-hooks/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221995802,"owners_count":16913563,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["frontend","hooks","hooks-and-redux","hooks-and-resolvers","hooks-api","hooks-api-react","hooks-async","hooks-folder","hooks-library","hooks-props-and-state","hookstate","javascript","react","react-components","react-hooks","reactjs","reactjs-components","typescript","ui","web-development"],"created_at":"2024-07-31T10:00:32.540Z","updated_at":"2024-10-29T05:31:22.823Z","avatar_url":"https://github.com/sergeyleschev.png","language":"JavaScript","funding_links":[],"categories":["Ready-Made Reactjs Hooks"],"sub_categories":[],"readme":"\n# S.Leschev: React Custom Hooks\n### Supercharge Your Projects with My Custom Hooks\n\nIn this repository, we dive into the world of custom React hooks and explore the incredible potential they hold for supercharging your work projects. With over 20 carefully crafted hooks at your disposal, I personally utilize these hooks in my own work projects, and now I'm excited to share them with you. From enhancing functionality to streamlining workflows, these custom hooks are designed to empower developers and deliver user-friendly experiences. Join us on this journey as we unleash the power of these 20+ hooks and unlock new levels of productivity and innovation in your React projects.\n\nReact Hooks are a feature introduced in React version 16.8 that revolutionized the way developers write and manage stateful logic in functional components. Previously, stateful logic could only be implemented in class components using lifecycle methods. However, with React Hooks, developers can now utilize state and other React features directly in functional components. Hooks provide a way to easily reuse stateful logic across multiple components, improving code reusability and reducing complexity. They enable developers to break down complex components into smaller, more manageable pieces, resulting in cleaner and more maintainable code. Hooks, such as useState and useEffect, allow developers to manage component state and handle side effects effortlessly. With their simplicity and flexibility, React Hooks have become an essential tool for building modern, efficient, and scalable React applications.\n\nReact custom hooks are reusable functions that allow developers to abstract and encapsulate complex logic in a reusable manner. Custom hooks are created by combining existing React hooks or other custom hooks. They enable developers to extract common logic from components and share it across different parts of an application. Custom hooks follow a naming convention of using the \"use\" prefix, which allows them to leverage the benefits of React's rules of hooks. By creating custom hooks, developers can modularize and organize their code, making it more readable, maintainable, and testable. These hooks can encapsulate any kind of logic, such as API calls, form handling, state management, or even abstracting external libraries. React custom hooks are a powerful tool that promotes code reusability and reduces duplication, making development more efficient and scalable.\n\nReact Custom Hooks @ 2023, S. Leschev. Google Engineering Level: L6+\n\n# Table of Contents\n- [S.Leschev: React Custom Hooks](#sleschev-react-custom-hooks)\n  - [1. `useArray`](#1-usearray)\n  - [2. `useAsync`](#2-useasync)\n  - [3. `useClickOutside`](#3-useclickoutside)\n  - [4. `useCookie`](#4-usecookie)\n  - [5. `useCopyToClipboard`](#5-usecopytoclipboard)\n  - [6. `useDarkMode`](#6-usedarkmode)\n  - [7. `useDebounce`](#7-usedebounce)\n  - [8. `useDebugInformation`](#8-usedebuginformation)\n  - [9. `useDeepCompareEffect`](#9-usedeepcompareeffect)\n  - [10. `useEffectOnce`](#10-useeffectonce)\n  - [11. `useEventListener`](#11-useeventlistener)\n  - [12. `useFetch`](#12-usefetch)\n  - [13. `useGeolocation`](#13-usegeolocation)\n  - [14. `useHover`](#14-usehover)\n  - [15. `useLongPress`](#15-uselongpress)\n  - [16. `useMediaQuery`](#16-usemediaquery)\n  - [17. `useOnlineStatus`](#17-useonlinestatus)\n  - [18. `useOnScreen`](#18-useonscreen)\n  - [19. `usePrevious`](#19-useprevious)\n  - [20. `useRenderCount`](#20-userendercount)\n  - [21. `useScript`](#21-usescript)\n  - [22. `useStateWithHistory`](#22-usestatewithhistory)\n  - [23. `useStateWithValidation`](#23-usestatewithvalidation)\n  - [24. `useStorage`](#24-usestorage)\n  - [25. `useTimeout`](#25-usetimeout)\n  - [26. `useToggle`](#26-usetoggle)\n  - [27. `useTranslation`](#27-usetranslation)\n  - [28. `useUpdateEffect`](#28-useupdateeffect)\n  - [29. `useWindowSize`](#29-usewindowsize)\n  - [Available Scripts](#available-scripts)\n    - [`npm start`](#npm-start)\n    - [`npm test`](#npm-test)\n    - [`npm run build`](#npm-run-build)\n    - [`npm run eject`](#npm-run-eject)\n- [🏆 Awards](#-awards)\n    - [Ranking #Dev: Global TOP 200 (Certificate)](#ranking-dev-global-top-200-certificate)\n  - [Contacts](#contacts)\n\n\u003cbr /\u003e\n\n## 1. [`useArray`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useArray/useArray.js)\n\n```javascript\nimport { useState } from \"react\"\n\nexport default function useArray(defaultValue) {\n    const [array, setArray] = useState(defaultValue)\n\n    function push(element) {\n        setArray(a =\u003e [...a, element])\n    }\n\n    function filter(callback) {\n        setArray(a =\u003e a.filter(callback))\n    }\n\n    function update(index, newElement) {\n        setArray(a =\u003e [\n            ...a.slice(0, index),\n            newElement,\n            ...a.slice(index + 1, a.length),\n        ])\n    }\n\n    function remove(index) {\n        setArray(a =\u003e [...a.slice(0, index), ...a.slice(index + 1, a.length)])\n    }\n\n    function clear() {\n        setArray([])\n    }\n\n    return { array, set: setArray, push, filter, update, remove, clear }\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useArray hook utilizes the useState hook from React to initialize and manage the array state. It returns an object with the following functions:\n\n- push(element): Adds the specified element to the array.\n- filter(callback): Filters the array based on the provided callback function, removing elements that don't satisfy the condition.\n- update(index, newElement): Replaces the element at the specified index with the newElement.\n- remove(index): Removes the element at the specified index from the array.\n- clear(): Clears the array, setting it to an empty array.\n\nThe advantages of using this custom hook are twofold: it simplifies the management of array states and provides a cleaner and more readable code structure. With the useArray hook, you can easily add, update, remove, filter, and clear elements in an array without dealing with complex logic.\n\n```javascript\nimport useArray from \"./useArray\"\n\nexport default function ArrayComponent() {\n    const { array, set, push, remove, filter, update, clear } = useArray([\n        1, 2, 3, 4, 5, 6,\n    ])\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{array.join(\", \")}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e push(7)}\u003eAdd 7\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e update(1, 9)}\u003eChange Second Element To 9\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e remove(1)}\u003eRemove Second Element\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e filter(n =\u003e n \u003c 3)}\u003e\n                Keep Numbers Less Than 4\n            \u003c/button\u003e\n            \u003cbutton onClick={() =\u003e set([1, 2])}\u003eSet To 1, 2\u003c/button\u003e\n            \u003cbutton onClick={clear}\u003eClear\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 2. [`useAsync`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useAsync/useAsync.js)\n\n```javascript\nimport { useCallback, useEffect, useState } from \"react\"\n\nexport default function useAsync(callback, dependencies = []) {\n    const [loading, setLoading] = useState(true)\n    const [error, setError] = useState()\n    const [value, setValue] = useState()\n\n    const callbackMemoized = useCallback(() =\u003e {\n        setLoading(true)\n        setError(undefined)\n        setValue(undefined)\n        callback()\n            .then(setValue)\n            .catch(setError)\n            .finally(() =\u003e setLoading(false))\n    }, dependencies)\n\n    useEffect(() =\u003e {\n        callbackMemoized()\n    }, [callbackMemoized])\n\n    return { loading, error, value }\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useAsync hook takes in a callback function that performs the asynchronous operation and an optional array of dependencies. It returns an object with three properties: loading, error, and value. The loading property indicates whether the operation is currently in progress, while the error property holds any error messages encountered during the process. Finally, the value property contains the resolved value of the asynchronous operation.\n\nOne of the significant advantages of useAsync is its ability to memoize the callback function using useCallback. This ensures that the callback is only recreated when the dependencies change, preventing unnecessary re-renders and optimizing performance. Additionally, the hook employs the useState and useEffect hooks to manage the loading state and invoke the memoized callback function when necessary.\n\nUseAsync can be employed in a wide range of scenarios. Whether you're fetching data from an API, performing computations, or handling form submissions, this custom hook simplifies the management of asynchronous operations throughout your React components. Its flexibility and ease of use make it a valuable addition to any React project.\n\nBy utilizing useAsync, you can streamline your codebase, enhance reusability, and maintain a consistent and reliable user experience. Give it a try in your next React project and witness the power of simplified asynchronous operations.\n\n```javascript\nimport useAsync from \"./useAsync\"\n\nexport default function AsyncComponent() {\n    const { loading, error, value } = useAsync(() =\u003e {\n        return new Promise((resolve, reject) =\u003e {\n            const success = false\n            setTimeout(() =\u003e {\n                success ? resolve(\"Hi\") : reject(\"Error\")\n            }, 1000)\n        })\n    })\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003eLoading: {loading.toString()}\u003c/div\u003e\n            \u003cdiv\u003e{error}\u003c/div\u003e\n            \u003cdiv\u003e{value}\u003c/div\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\u003cbr /\u003e\n\n## 3. [`useClickOutside`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useClickOutside/useClickOutside.js)\n\n```javascript\nimport useEventListener from \"../useEventListener/useEventListener\"\n\nexport default function useClickOutside(ref, cb) {\n    useEventListener(\"click\", e =\u003e {\n        if (ref.current == null || ref.current.contains(e.target)) return\n        cb(e)\n    }, document)\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useClickOutside hook is designed to simplify the process of detecting clicks outside a specified component. By utilizing the useEventListener hook, it listens for click events on the document level, allowing you to trigger a callback function when a click occurs outside the provided component's reference.\n\nOne of the main advantages of useClickOutside is its ease of use. Simply import the hook into your component and pass the desired component's reference and a callback function. The hook takes care of the event listener setup and cleanup, saving you time and effort. Plus, it works seamlessly with functional components using the useState and useRef hooks.\n\nThe potential applications for useClickOutside are endless. It is particularly useful when implementing modal windows, dropdown menus, or any element that should be closed when a user interacts with anything outside of it. By incorporating useClickOutside, you can enhance the user experience by providing intuitive and efficient interactions.\n\nTo see useClickOutside in action, take a look at the example above. In this case, the ClickOutsideComponent utilizes the hook to toggle the visibility of a modal window. When the user clicks outside the modal, the provided callback function sets the open state to false, closing the modal. This way, the component offers a sleek and user-friendly way to manage the modal's visibility.\n\n```javascript\nimport { useRef, useState } from \"react\"\nimport useClickOutside from \"./useClickOutside\"\n\nexport default function ClickOutsideComponent() {\n    const [open, setOpen] = useState(false)\n    const modalRef = useRef()\n\n    useClickOutside(modalRef, () =\u003e {\n        if (open) setOpen(false)\n    })\n\n    return (\n        \u003c\u003e\n            \u003cbutton onClick={() =\u003e setOpen(true)}\u003eOpen\u003c/button\u003e\n            \u003cdiv\n                ref={modalRef}\n                style={{\n                    display: open ? \"block\" : \"none\",\n                    backgroundColor: \"blue\",\n                    color: \"white\",\n                    width: \"100px\",\n                    height: \"100px\",\n                    position: \"absolute\",\n                    top: \"calc(50% - 50px)\",\n                    left: \"calc(50% - 50px)\",\n                }}\n            \u003e\n                \u003cspan\u003eModal\u003c/span\u003e\n            \u003c/div\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 4. [`useCookie`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useCookie/useCookie.js)\n\n```javascript\nimport { useState, useCallback } from \"react\"\nimport Cookies from \"js-cookie\"\n\nexport default function useCookie(name, defaultValue) {\n    const [value, setValue] = useState(() =\u003e {\n        const cookie = Cookies.get(name)\n        if (cookie) return cookie\n        Cookies.set(name, defaultValue)\n        return defaultValue\n    })\n\n    const updateCookie = useCallback(\n        (newValue, options) =\u003e {\n            Cookies.set(name, newValue, options)\n            setValue(newValue)\n        },\n        [name]\n    )\n\n    const deleteCookie = useCallback(() =\u003e {\n        Cookies.remove(name)\n        setValue(null)\n    }, [name])\n\n    return [value, updateCookie, deleteCookie]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useCookie hook allows you to effortlessly handle cookies by providing a concise interface. Upon initialization, useCookie retrieves the cookie value with the specified name. If the cookie exists, it returns its value; otherwise, it sets the cookie to the default value provided. This ensures a seamless experience for your users, as the desired data is readily available.\n\nOne of the key advantages of this custom hook is the ability to update the cookie value. The updateCookie function, returned by useCookie, enables you to modify the value of the cookie. By invoking this function with a new value and optional options, such as expiration or path, you can instantly update the cookie. Additionally, the hook conveniently updates the state, keeping your application in sync with the modified cookie.\n\nIn scenarios where you need to remove a cookie, the deleteCookie function comes to the rescue. Simply call this function, and it will remove the specified cookie from the browser. The hook takes care of updating the state, ensuring that your application reflects the removal of the cookie.\n\nThe useCookie custom hook is highly versatile and can be utilized in various contexts. It is particularly beneficial when working with user preferences, authentication tokens, or any data that needs to persist across different sessions. Whether you are building a simple login form, a shopping cart, or a feature-rich application, useCookie simplifies cookie management, saving you valuable development time.\n\n```javascript\nimport useCookie from \"./useCookie\"\n\nexport default function CookieComponent() {\n    const [value, update, remove] = useCookie(\"name\", \"John\")\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003e{value}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e update(\"Sally\")}\u003eChange Name To Sally\u003c/button\u003e\n            \u003cbutton onClick={remove}\u003eDelete Name\u003c/button\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 5. [`useCopyToClipboard`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useCopyToClipboard/useCopyToClipboard.js)\n\n```javascript\nimport { useState } from \"react\"\nimport copy from \"copy-to-clipboard\"\n\nexport default function useCopyToClipboard() {\n    const [value, setValue] = useState()\n    const [success, setSuccess] = useState()\n\n    const copyToClipboard = (text, options) =\u003e {\n        const result = copy(text, options)\n        if (result) setValue(text)\n        setSuccess(result)\n    }\n\n    return [copyToClipboard, { value, success }]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nCopying text to the clipboard in a React application can be a tedious task. To simplify this process, I've created a powerful custom hook called useCopyToClipboard. With just a few lines of code, this hook streamlines the copy-to-clipboard functionality, providing developers with a hassle-free solution.\n\nThe useCopyToClipboard hook utilizes the useState hook from React, along with the copy-to-clipboard library, to achieve its functionality. By invoking this custom hook, you gain access to two essential features: copyToClipboard and its accompanying state variables.\n\nThe copyToClipboard function takes in two parameters: the text to be copied and optional configuration options. It handles the copying process and updates the state accordingly. When successful, the provided text is set as the current value, and the success state is set to true. Conversely, if the copying fails, the success state remains false.\n\nTo demonstrate the power of useCopyToClipboard, let's consider a practical implementation. Suppose you have a component called CopyToClipboardComponent. By utilizing this custom hook, you can effortlessly copy text by invoking the copyToClipboard function, which accepts the desired text as an argument. The success state variable provides immediate feedback, allowing you to display appropriate messages or UI elements based on the copying outcome.\n\nThe useCopyToClipboard hook is incredibly versatile and can be employed in various scenarios. It is particularly useful in situations where copying text, such as URLs, shareable content, or user-generated data, is required. Whether you're building a blogging platform, a social media application, or any other React-based project, useCopyToClipboard simplifies the process of copying text, enhancing user experience and productivity.\n\n```javascript\nimport useCopyToClipboard from \"./useCopyToClipboard\"\n\nexport default function CopyToClipboardComponent() {\n    const [copyToClipboard, { success }] = useCopyToClipboard()\n\n    return (\n        \u003c\u003e\n            \u003cbutton onClick={() =\u003e copyToClipboard(\"This was copied\")}\u003e\n                {success ? \"Copied\" : \"Copy Text\"}\n            \u003c/button\u003e\n            \u003cinput type=\"text\" /\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 6. [`useDarkMode`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useDarkMode/useDarkMode.js)\n\n```javascript\nimport { useEffect } from \"react\"\nimport useMediaQuery from \"../useMediaQuery/useMediaQuery\"\nimport { useLocalStorage } from \"../useStorage/useStorage\"\n\nexport default function useDarkMode() {\n    const [darkMode, setDarkMode] = useLocalStorage(\"useDarkMode\")\n    const prefersDarkMode = useMediaQuery(\"(prefers-color-scheme: dark)\")\n    const enabled = darkMode ?? prefersDarkMode\n\n    useEffect(() =\u003e {\n        document.body.classList.toggle(\"dark-mode\", enabled)\n    }, [enabled])\n\n    return [enabled, setDarkMode]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThis custom hook combines two other handy hooks, [`useMediaQuery`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useMediaQuery/useMediaQuery.js) and [`useStorage`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useStorage/useStorage.js), to provide a seamless dark mode experience. It automatically detects the user's preferred color scheme and persists the dark mode state in the browser's local storage.\n\nOne of the main advantages of \"useDarkMode\" is its simplicity. With just a few lines of code, you can enable dark mode in your React application. By invoking this hook, you'll receive the current dark mode state and a function to toggle it.\n\nThe \"useDarkMode\" hook dynamically updates the HTML body class to apply the \"dark-mode\" styling whenever dark mode is enabled. This approach ensures consistency across all components without the need for manual class manipulation.\n\n```css\nbody.dark-mode {\n    background-color: #333;\n}\n```\n\nYou can use the \"useDarkMode\" hook in various scenarios. Whether you're building a blog, e-commerce platform, or a content-heavy application, dark mode can enhance the user experience, reduce eye strain, and conserve device battery life. The possibilities are endless, and this custom hook makes it a breeze to implement.\n\nTo make it even easier, I've included a simple example component, \"DarkModeComponent,\" that showcases how to use the \"useDarkMode\" hook. By clicking the \"Toggle Dark Mode\" button, you can instantly switch between light and dark themes. The button's appearance changes dynamically, reflecting the current mode.\n\n```javascript\nimport useDarkMode from \"./useDarkMode\"\nimport \"./body.css\"\n\nexport default function DarkModeComponent() {\n    const [darkMode, setDarkMode] = useDarkMode()\n\n    return (\n        \u003cbutton\n            onClick={() =\u003e setDarkMode(prevDarkMode =\u003e !prevDarkMode)}\n            style={{\n                border: `1px solid ${darkMode ? \"white\" : \"black\"}`,\n                background: \"none\",\n                color: darkMode ? \"white\" : \"black\",\n            }}\n        \u003e\n            Toggle Dark Mode\n        \u003c/button\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 7. [`useDebounce`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useDebounce/useDebounce.js)\n\n```javascript\nimport { useEffect } from \"react\"\nimport useTimeout from \"../useTimeout/useTimeout\"\n\nexport default function useDebounce(callback, delay, dependencies) {\n    const { reset, clear } = useTimeout(callback, delay)\n    useEffect(reset, [...dependencies, reset])\n    useEffect(clear, [])\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useDebounce hook leverages the useTimeout hook internally to delay the execution of a callback function until a specified delay has passed. By doing so, it prevents frequent updates caused by rapid input changes or repeated events, allowing for smoother interactions and reduced resource consumption.\n\nOne of the main advantages of useDebounce is its simplicity and flexibility. By wrapping your callback function, delay duration, and any dependencies in this custom hook, you can effortlessly implement debouncing functionality without cluttering your component code. The hook takes care of managing the timeout and clears it when necessary, ensuring that the callback is only triggered after the specified delay and with the latest dependencies.\n\nWhere can you use useDebounce? The possibilities are endless! This custom hook is particularly beneficial in scenarios where you need to handle user input, such as search bars or form fields, where you want to delay the execution of an action until the user has finished typing or interacting. It's also useful for optimizing network requests, ensuring that requests are sent only after the user has stopped typing or selecting options.\n\nIn the example above, we showcase the power of useDebounce by implementing a simple counter component called DebounceComponent. Each time the user clicks the \"Increment\" button, the count state updates. However, instead of immediately alerting the count value, we debounce the alert function using useDebounce. The count value will only be alerted after a 1-second delay, effectively preventing excessive alerts when the button is clicked rapidly.\n\n```javascript\nimport { useState } from \"react\"\nimport useDebounce from \"./useDebounce\"\n\nexport default function DebounceComponent() {\n    const [count, setCount] = useState(10)\n    useDebounce(() =\u003e alert(count), 1000, [count])\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{count}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setCount(c =\u003e c + 1)}\u003eIncrement\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 8. [`useDebugInformation`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useDebugInformation/useDebugInformation.js)\n\n```javascript\nimport { useEffect, useRef } from \"react\"\nimport useRenderCount from \"../useRenderCount/useRenderCount\"\n\nexport default function useDebugInformation(componentName, props) {\n    const count = useRenderCount()\n    const changedProps = useRef({})\n    const previousProps = useRef(props)\n    const lastRenderTimestamp = useRef(Date.now())\n\n    const propKeys = Object.keys({ ...props, ...previousProps })\n    changedProps.current = propKeys.reduce((obj, key) =\u003e {\n        if (props[key] === previousProps.current[key]) return obj\n        return {\n            ...obj,\n            [key]: { previous: previousProps.current[key], current: props[key] },\n        }\n    }, {})\n    const info = {\n        count,\n        changedProps: changedProps.current,\n        timeSinceLastRender: Date.now() - lastRenderTimestamp.current,\n        lastRenderTimestamp: lastRenderTimestamp.current,\n    }\n\n    useEffect(() =\u003e {\n        previousProps.current = props\n        lastRenderTimestamp.current = Date.now()\n        console.log(\"[debug-info]\", componentName, info)\n    })\n\n    return info\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nWhen it comes to debugging React components, having access to detailed information about renders and prop changes can be incredibly useful. That's where the useDebugInformation custom hook comes in. Created by [Your Name], this advanced hook provides developers with valuable insights into their components' behavior and helps identify performance bottlenecks or unexpected rendering patterns.\n\nOne of the main advantages of useDebugInformation is its simplicity. By integrating just a few lines of code into your component, you gain access to a wealth of debugging data. The hook tracks the number of renders, changed props, time since the last render, and the timestamp of the last render. This comprehensive information empowers you to analyze component behavior more effectively and make informed decisions when optimizing your application.\n\nThe useDebugInformation hook can be applied in various scenarios. For instance, imagine you're working on a complex form component where certain props trigger updates or affect rendering. By utilizing useDebugInformation, you can easily monitor how these props impact your component's performance and whether unnecessary re-renders are occurring. Additionally, the hook can be invaluable when investigating why a specific component is not updating as expected or when fine-tuning optimizations in a performance-critical application.\n\nTo implement useDebugInformation, simply import it into your React component, along with any other necessary hooks. In the example provided, the DebugInformationComponent utilizes the useDebugInformation hook within the ChildComponent. By passing the component name and props to the hook, you gain access to an info object containing all the relevant debugging data. This object can then be displayed or logged for further analysis.\n\n```javascript\nimport useDebugInformation from \"./useDebugInformation\"\nimport useToggle from \"../useToggle/useToggle\"\nimport { useState } from \"react\"\n\nexport default function DebugInformationComponent() {\n    const [boolean, toggle] = useToggle(false)\n    const [count, setCount] = useState(0)\n\n    return (\n        \u003c\u003e\n            \u003cChildComponent boolean={boolean} count={count} /\u003e\n            \u003cbutton onClick={toggle}\u003eToggle\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setCount(prevCount =\u003e prevCount + 1)}\u003e\n                Increment\n            \u003c/button\u003e\n        \u003c/\u003e\n    )\n}\n\nfunction ChildComponent(props) {\n    const info = useDebugInformation(\"ChildComponent\", props)\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003e{props.boolean.toString()}\u003c/div\u003e\n            \u003cdiv\u003e{props.count}\u003c/div\u003e\n            \u003cdiv\u003e{JSON.stringify(info, null, 2)}\u003c/div\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 9. [`useDeepCompareEffect`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useDeepCompareEffect/useDeepCompareEffect.js)\n\n```javascript\nimport { useEffect, useRef } from \"react\"\nimport isEqual from \"lodash/fp/isEqual\"\n\nexport default function useDeepCompareEffect(callback, dependencies) {\n    const currentDependenciesRef = useRef()\n\n    if (!isEqual(currentDependenciesRef.current, dependencies)) {\n        currentDependenciesRef.current = dependencies\n    }\n\n    useEffect(callback, [currentDependenciesRef.current])\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nManaging dependencies in React can be a challenge, especially when dealing with complex data structures or nested objects. That's where the useDeepCompareEffect custom hook comes in handy. Created to tackle the limitations of the default useEffect hook, useDeepCompareEffect ensures that the effect callback is only triggered when the dependencies have deeply changed, using lodash's isEqual function for accurate comparison.\n\nOne of the key advantages of useDeepCompareEffect is its ability to prevent unnecessary re-renders. By performing a deep comparison between the current and previous dependencies, the hook intelligently determines if the effect should be triggered, leading to optimized performance in scenarios where shallow comparisons fall short.\n\nThis custom hook can be especially useful when dealing with complex state objects, such as when you have deeply nested data structures or multiple interconnected states that need to be tracked. It enables you to define dependencies that accurately reflect the specific changes you want to track, ensuring that the effect is executed only when it is absolutely necessary.\n\nYou can easily incorporate useDeepCompareEffect into your React components by importing it and utilizing it in place of the traditional useEffect hook. By passing the effect callback and an array of dependencies, you can ensure that your effect runs efficiently and effectively.\n\n```javascript\nimport { useEffect, useState, useRef } from \"react\"\nimport useDeepCompareEffect from \"./useDeepCompareEffect\"\n\nexport default function DeepCompareEffectComponent() {\n    const [age, setAge] = useState(0)\n    const [otherCount, setOtherCount] = useState(0)\n    const useEffectCountRef = useRef()\n    const useDeepCompareEffectCountRef = useRef()\n\n    const person = { age: age, name: \"Sergey\" }\n\n    useEffect(() =\u003e {\n        useEffectCountRef.current.textContent =\n            parseInt(useEffectCountRef.current.textContent) + 1\n    }, [person])\n\n    useDeepCompareEffect(() =\u003e {\n        useDeepCompareEffectCountRef.current.textContent =\n            parseInt(useDeepCompareEffectCountRef.current.textContent) + 1\n    }, [person])\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e\n                useEffect: \u003cspan ref={useEffectCountRef}\u003e0\u003c/span\u003e\n            \u003c/div\u003e\n            \u003cdiv\u003e\n                useDeepCompareEffect: \u003cspan ref={useDeepCompareEffectCountRef}\u003e0\u003c/span\u003e\n            \u003c/div\u003e\n            \u003cdiv\u003eOther Count: {otherCount}\u003c/div\u003e\n            \u003cdiv\u003e{JSON.stringify(person)}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setAge(currentAge =\u003e currentAge + 1)}\u003e\n                Increment Age\n            \u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setOtherCount(count =\u003e count + 1)}\u003e\n                Increment Other Count\n            \u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 10. [`useEffectOnce`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useEffectOnce/useEffectOnce.js)\n\n```javascript\nimport { useEffect } from \"react\"\n\nexport default function useEffectOnce(cb) {\n    useEffect(cb, [])\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useEffectOnce hook is designed to streamline the process of running effects only once when a component mounts. With just a few lines of code, you can eliminate the need to manually specify an empty dependency array ([]). Here's how it works:\n\nBy encapsulating the repetitive useEffect pattern, useEffectOnce allows you to focus on the logic within the effect function itself. This elegant solution saves you from writing boilerplate code repeatedly and helps keep your component files clean and concise.\n\nTo showcase the power of useEffectOnce, let's consider a practical example:\n\n```javascript\nimport { useState } from \"react\"\nimport useEffectOnce from \"./useEffectOnce\"\n\nexport default function EffectOnceComponent() {\n    const [count, setCount] = useState(0)\n\n    useEffectOnce(() =\u003e alert(\"Hi\"))\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003e{count}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setCount(c =\u003e c + 1)}\u003eIncrement\u003c/button\u003e\n        \u003c/\u003e\n    )\n}\n```\n\nIn this case, when EffectOnceComponent mounts, the useEffectOnce hook triggers the alert \"Hi\" exactly once. It frees you from manually managing the effect dependencies and ensures your effect runs efficiently.\n\nThis custom hook is incredibly versatile and can be utilized in various scenarios. Whether you need to fetch initial data, set up event listeners, or initialize third-party libraries, useEffectOnce simplifies the process and promotes cleaner code organization.\n\n\u003cbr /\u003e\n\n## 11. [`useEventListener`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useEventListener/useEventListener.js)\n\n```javascript\nimport { useEffect, useRef } from \"react\"\n\nexport default function useEventListener(\n    eventType,\n    callback,\n    element = window\n) {\n    const callbackRef = useRef(callback)\n\n    useEffect(() =\u003e {\n        callbackRef.current = callback\n    }, [callback])\n\n    useEffect(() =\u003e {\n        if (element == null) return\n        const handler = e =\u003e callbackRef.current(e)\n        element.addEventListener(eventType, handler)\n\n        return () =\u003e element.removeEventListener(eventType, handler)\n    }, [eventType, element])\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the major advantages of useEventListener is its flexibility. You can specify the event type, callback function, and even the element where the event listener should be attached. This flexibility allows you to tailor event handling to your specific needs, enhancing the reusability of your code.\n\nThe hook also takes advantage of the useRef hook to maintain a stable reference to the callback function. This ensures that the most up-to-date version of the callback is used, even if it changes during the component's lifecycle. This dynamic behavior enables you to handle events with precision and respond to changes in your application's state.\n\nThe useEventListener hook is a versatile tool that can be used in a wide range of scenarios. Whether you need to capture keyboard events, listen for scroll events, or interact with user input, this hook has got you covered. Its simplicity and elegance make it an ideal choice for any React project, from small-scale applications to large-scale enterprise solutions.\n\nTo demonstrate the power of useEventListener, consider the EventListenerComponent provided. It utilizes the hook to track the last key pressed by the user. With just a few lines of code, you can effortlessly handle keydown events and update the component's state accordingly. This example highlights the ease and effectiveness of useEventListener, showcasing its ability to simplify event-driven interactions in React applications.\n\n```javascript\nimport { useState } from \"react\"\nimport useEventListener from \"./useEventListener\"\n\nexport default function EventListenerComponent() {\n    const [key, setKey] = useState(\"\")\n    useEventListener(\"keydown\", e =\u003e {\n        setKey(e.key)\n    })\n\n    return \u003cdiv\u003eLast Key: {key}\u003c/div\u003e\n}\n```\n\n\u003cbr /\u003e\n\n## 12. [`useFetch`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useFetch/useFetch.js)\n\n```javascript\nimport useAsync from \"../useAsync/useAsync\"\n\nconst DEFAULT_OPTIONS = {\n    headers: { \"Content-Type\": \"application/json\" },\n}\n\nexport default function useFetch(url, options = {}, dependencies = []) {\n    return useAsync(() =\u003e {\n        return fetch(url, { ...DEFAULT_OPTIONS, ...options }).then(res =\u003e {\n            if (res.ok) return res.json()\n            return res.json().then(json =\u003e Promise.reject(json))\n        })\n    }, dependencies)\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the key advantages of useFetch is its simplicity. By abstracting away the fetch logic into a reusable hook, developers can quickly and effortlessly make HTTP requests and handle responses without repetitive boilerplate code. With just a few lines, useFetch handles the network request, parses the JSON response, and provides the resulting data.\n\nThe useFetch hook also offers flexibility through its customizable options parameter. Developers can pass additional headers, query parameters, or request options as needed, ensuring compatibility with various APIs. The hook follows best practices by providing default options for setting the Content-Type header as application/json, promoting clean and consistent code.\n\nAnother noteworthy feature of useFetch is its support for dependency tracking. By specifying an array of dependencies, developers can control when the hook triggers a new request. This feature enhances performance optimization, allowing for selective data updates based on changes in the dependency array.\n\nThis versatile hook can be utilized in numerous scenarios. For example, in a React component that needs to fetch and display dynamic data, useFetch simplifies the process. It takes care of handling loading and error states, keeping the component clean and focused on rendering the received data. Additionally, useFetch is particularly useful in scenarios where the fetched data is based on dynamic variables or user interactions, as demonstrated in the FetchComponent example.\n\n```javascript\nimport { useState } from \"react\"\nimport useFetch from \"./useFetch\"\n\nexport default function FetchComponent() {\n    const [id, setId] = useState(1)\n    const { loading, error, value } = useFetch(\n        `https://jsonplaceholder.typicode.com/todos/${id}`,\n        {},\n        [id]\n    )\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{id}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setId(currentId =\u003e currentId + 1)}\u003e\n                Increment ID\n            \u003c/button\u003e\n            \u003cdiv\u003eLoading: {loading.toString()}\u003c/div\u003e\n            \u003cdiv\u003e{JSON.stringify(error, null, 2)}\u003c/div\u003e\n            \u003cdiv\u003e{JSON.stringify(value, null, 2)}\u003c/div\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 13. [`useGeolocation`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useGeolocation/useGeolocation.js)\n\n```javascript\nimport { useState, useEffect } from \"react\"\n\nexport default function useGeolocation(options) {\n    const [loading, setLoading] = useState(true)\n    const [error, setError] = useState()\n    const [data, setData] = useState({})\n\n    useEffect(() =\u003e {\n        const successHandler = e =\u003e {\n            setLoading(false)\n            setError(null)\n            setData(e.coords)\n        }\n        const errorHandler = e =\u003e {\n            setError(e)\n            setLoading(false)\n        }\n        navigator.geolocation.getCurrentPosition(\n            successHandler,\n            errorHandler,\n            options\n        )\n        const id = navigator.geolocation.watchPosition(\n            successHandler,\n            errorHandler,\n            options\n        )\n        return () =\u003e navigator.geolocation.clearWatch(id)\n    }, [options])\n\n    return { loading, error, data }\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useGeolocation hook utilizes React's useState and useEffect hooks to manage the state of loading, errors, and geolocation data. It takes an optional \"options\" parameter to customize the geolocation behavior, allowing you to fine-tune the accuracy and other settings based on your specific needs.\n\nOne of the key advantages of useGeolocation is its simplicity. By encapsulating the complex logic required for geolocation access and handling, this hook provides a clean and reusable solution. The hook automatically handles the loading state, updating it when geolocation data is being fetched, and sets the error state if any issues arise during the process.\n\nThe useGeolocation hook also incorporates the watchPosition method from the Geolocation API, which enables continuous monitoring of the user's position. This can be useful in scenarios where real-time updates of the user's location are required, such as in tracking applications or interactive maps.\n\nTo use this hook, simply import useGeolocation into your component and destructure the loading, error, and data variables. The data object contains the latitude and longitude values, allowing you to display the user's location on your UI effortlessly. The loading variable informs you of the current state of geolocation retrieval, and the error variable provides any error messages, if applicable.\n\nThe GeolocationComponent showcased above demonstrates a basic implementation of useGeolocation. It renders the loading state, error message (if any), and the user's latitude and longitude values. With just a few lines of code, you can seamlessly integrate geolocation functionality into your React applications.\n\n```javascript\nimport useGeolocation from \"./useGeolocation\"\n\nexport default function GeolocationComponent() {\n    const {\n        loading,\n        error,\n        data: { latitude, longitude },\n    } = useGeolocation()\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003eLoading: {loading.toString()}\u003c/div\u003e\n            \u003cdiv\u003eError: {error?.message}\u003c/div\u003e\n            \u003cdiv\u003e\n                {latitude} x {longitude}\n            \u003c/div\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 14. [`useHover`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useHover/useHover.js)\n\n```javascript\nimport { useState } from \"react\"\nimport useEventListener from \"../useEventListener/useEventListener\"\n\nexport default function useHover(ref) {\n    const [hovered, setHovered] = useState(false)\n\n    useEventListener(\"mouseover\", () =\u003e setHovered(true), ref.current)\n    useEventListener(\"mouseout\", () =\u003e setHovered(false), ref.current)\n\n    return hovered\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThis lightweight hook leverages the useState and [useEventListener](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useEventListener/useEventListener.js) hooks from React to keep track of the hover state. By simply passing a ref to the useHover hook, you can start receiving accurate hover events. The hook listens for \"mouseover\" and \"mouseout\" events, updating the hovered state accordingly.\n\nOne of the key advantages of useHover is its simplicity and reusability. By encapsulating the hover logic within the hook, you can easily use it across multiple components without duplicating code. This promotes clean and maintainable code, saving you time and effort in the long run.\n\nUseHover can be used in a variety of scenarios. Whether you need to highlight an element on hover, trigger additional actions, or dynamically change styles, this custom hook has got you covered. It provides a seamless way to enhance the interactivity and user experience of your React components.\n\nTo demonstrate its power, consider the HoverComponent example above. By applying the useHover hook to the elementRef, the background color of the div dynamically changes between blue and red depending on the hover state. This simple yet effective implementation showcases the potential of useHover in creating interactive and engaging UI components.\n\n```javascript\nimport { useRef } from \"react\"\nimport useHover from \"./useHover\"\n\nexport default function HoverComponent() {\n    const elementRef = useRef()\n    const hovered = useHover(elementRef)\n\n    return (\n        \u003cdiv\n            ref={elementRef}\n            style={{\n                backgroundColor: hovered ? \"blue\" : \"red\",\n                width: \"100px\",\n                height: \"100px\",\n                position: \"absolute\",\n                top: \"calc(50% - 50px)\",\n                left: \"calc(50% - 50px)\",\n            }}\n        /\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 15. [`useLongPress`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useLongPress.js/useLongPress.js)\n\n```javascript\nimport useEventListener from \"../useEventListener/useEventListener\"\nimport useTimeout from \"../useTimeout/useTimeout\"\nimport useEffectOnce from \"../useEffectOnce/useEffectOnce\"\n\nexport default function useLongPress(ref, cb, { delay = 250 } = {}) {\n    const { reset, clear } = useTimeout(cb, delay)\n    useEffectOnce(clear)\n\n    useEventListener(\"mousedown\", reset, ref.current)\n    useEventListener(\"touchstart\", reset, ref.current)\n\n    useEventListener(\"mouseup\", clear, ref.current)\n    useEventListener(\"mouseleave\", clear, ref.current)\n    useEventListener(\"touchend\", clear, ref.current)\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the key advantages of useLongPress is its simplicity. By utilizing this hook, developers can easily define a long-press action on any element in their React application. With just a few lines of code, the hook takes care of handling the intricacies of tracking the long-press duration and triggering the associated callback function.\n\nThe useLongPress hook offers flexibility through customizable options. Developers can specify the desired delay for a long press, allowing them to fine-tune the duration required for an action to be triggered. Additionally, the hook intelligently integrates with other custom hooks like useTimeout, useEventListener, and useEffectOnce, enhancing code reusability and maintainability.\n\nThe applications for useLongPress are wide-ranging. Whether you're developing a touch-sensitive UI, implementing context menus, or creating custom gestures, this hook proves to be a valuable tool. From mobile applications to complex web interfaces, useLongPress provides an elegant solution for incorporating long-press interactions that elevate user engagement and improve overall usability.\n\n```javascript\nimport { useRef } from \"react\"\nimport useLongPress from \"./useLongPress\"\n\nexport default function LongPressComponent() {\n    const elementRef = useRef()\n    useLongPress(elementRef, () =\u003e alert(\"Long Press\"))\n\n    return (\n        \u003cdiv\n            ref={elementRef}\n            style={{\n                backgroundColor: \"red\",\n                width: \"100px\",\n                height: \"100px\",\n                position: \"absolute\",\n                top: \"calc(50% - 50px)\",\n                left: \"calc(50% - 50px)\",\n            }}\n        /\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 16. [`useMediaQuery`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useMediaQuery/useMediaQuery.js)\n\n```javascript\nimport { useState, useEffect } from \"react\"\nimport useEventListener from \"../useEventListener/useEventListener\"\n\nexport default function useMediaQuery(mediaQuery) {\n    const [isMatch, setIsMatch] = useState(false)\n    const [mediaQueryList, setMediaQueryList] = useState(null)\n\n    useEffect(() =\u003e {\n        const list = window.matchMedia(mediaQuery)\n        setMediaQueryList(list)\n        setIsMatch(list.matches)\n    }, [mediaQuery])\n\n    useEventListener(\"change\", e =\u003e setIsMatch(e.matches), mediaQueryList)\n\n    return isMatch\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useMediaQuery hook allows you to dynamically update your UI based on a given media query. Simply pass in the desired media query as a parameter, and the hook will return a boolean value indicating whether the media query matches the current viewport size.\n\nOne of the key advantages of this custom hook is its simplicity and reusability. With just a few lines of code, you can effortlessly implement responsive behavior throughout your application. Whether you need to conditionally render components, apply specific styles, or trigger different functionality based on screen size, useMediaQuery has got you covered.\n\nThis hook is not limited to specific use cases; it can be utilized in a variety of scenarios. For instance, you can use it to dynamically adjust the layout of a navigation menu, hide or show certain elements based on screen size, or even optimize the loading of data based on the available space. The possibilities are endless, and the useMediaQuery hook empowers you to deliver a seamless user experience across different devices and screen sizes.\n\n```javascript\nimport useMediaQuery from \"./useMediaQuery\"\n\nexport default function MediaQueryComponent() {\n    const isLarge = useMediaQuery(\"(min-width: 200px)\")\n\n    return \u003cdiv\u003eLarge: {isLarge.toString()}\u003c/div\u003e\n}\n```\n\n\u003cbr /\u003e\n\n## 17. [`useOnlineStatus`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useOnlineStatus/useOnlineStatus.js)\n\n```javascript\nimport { useState } from \"react\"\nimport useEventListener from \"../useEventListener/useEventListener\"\n\nexport default function useOnlineStatus() {\n    const [online, setOnline] = useState(navigator.onLine)\n\n    useEventListener(\"online\", () =\u003e setOnline(navigator.onLine))\n    useEventListener(\"offline\", () =\u003e setOnline(navigator.onLine))\n\n    return online\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the main advantages of \"useOnlineStatus\" is its simplicity. By importing and using this hook in your component, you can effortlessly access the online status of the user. The hook internally uses the \"navigator.onLine\" property to determine the initial online status and dynamically updates it whenever the user's connectivity changes.\n\nTo use this hook, all you need to do is call it within your functional component, just like the \"OnlineStatusComponent\" example demonstrates. It returns a boolean value indicating whether the user is currently online or offline. You can then utilize this information to provide real-time feedback to your users or make decisions based on their online status.\n\nThe \"useOnlineStatus\" hook can find applications in a wide range of scenarios. For instance, you can enhance user experience by displaying a visual indicator when the user loses their internet connection, allowing them to take appropriate actions. Additionally, you can conditionally render certain components or trigger specific behaviors based on the user's online status. The possibilities are endless, and this hook opens up new opportunities for building robust and responsive React applications.\n\n```javascript\nimport useOnlineStatus from \"./useOnlineStatus\"\n\nexport default function OnlineStatusComponent() {\n    const online = useOnlineStatus()\n\n    return \u003cdiv\u003e{online.toString()}\u003c/div\u003e\n}\n```\n\n\u003cbr /\u003e\n\n## 18. [`useOnScreen`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useOnScreen/useOnScreen.js)\n\n```javascript\nimport { useEffect, useState } from \"react\"\n\nexport default function useOnScreen(ref, rootMargin = \"0px\") {\n    const [isVisible, setIsVisible] = useState(false)\n\n    useEffect(() =\u003e {\n        if (ref.current == null) return\n        const observer = new IntersectionObserver(\n            ([entry]) =\u003e setIsVisible(entry.isIntersecting),\n            { rootMargin }\n        )\n        observer.observe(ref.current)\n        return () =\u003e {\n            if (ref.current == null) return\n            observer.unobserve(ref.current)\n        }\n    }, [ref.current, rootMargin])\n\n    return isVisible\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useOnScreen hook leverages the power of the Intersection Observer API, making it efficient and reliable. By simply providing a ref to the element you want to monitor, useOnScreen will notify you when it enters or exits the viewport.\n\nOne of the key advantages of useOnScreen is its simplicity. With just a few lines of code, you can detect if an element is visible and respond accordingly. This can be immensely useful in scenarios where you want to trigger animations, lazy load images, or load additional content as the user scrolls.\n\nTo use this hook, first import it into your component file. Then, create a ref using the useRef hook to target the desired element. Pass the ref as the first argument to the useOnScreen hook, and you're all set! You can also provide an optional rootMargin value to adjust the visible threshold.\n\nIn our example code, the OnScreenComponentComponent demonstrates how to use the useOnScreen hook. By attaching the ref to the second header element, we can display a \"(Visible)\" text when it enters the viewport. Feel free to customize the logic within your component to suit your specific needs.\n\n```javascript\nimport { useRef } from \"react\"\nimport useOnScreen from \"./useOnScreen\"\n\nexport default function OnScreenComponentComponent() {\n    const headerTwoRef = useRef()\n    const visible = useOnScreen(headerTwoRef, \"-100px\")\n\n    return (\n        \u003cdiv\u003e\n            \u003ch1\u003eHeader\u003c/h1\u003e\n            \u003cdiv\u003e\n              ...\n            \u003c/div\u003e\n            \u003ch1 ref={headerTwoRef}\u003eHeader 2 {visible \u0026\u0026 \"(Visible)\"}\u003c/h1\u003e\n            \u003cdiv\u003e\n              ...\n            \u003c/div\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 19. [`usePrevious`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/usePrevious/usePrevious.js)\n\n```javascript\nimport { useRef } from \"react\"\n\nexport default function usePrevious(value) {\n    const currentRef = useRef(value)\n    const previousRef = useRef()\n\n    if (currentRef.current !== value) {\n        previousRef.current = currentRef.current\n        currentRef.current = value\n    }\n\n    return previousRef.current\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe advantages of using usePrevious are remarkable. By using useRef, this hook efficiently stores the current and previous values, updating them whenever the value changes. By comparing the current and previous values, you can easily detect and respond to changes in your component's data.\n\nThis custom hook can be a game-changer in various scenarios. For instance, you can utilize usePrevious to compare and visualize changes in data, track state transitions, or implement undo/redo functionality. Additionally, it can be valuable in form handling, animations, and any situation where having access to the previous value is crucial for your application's logic.\n\nLet's take a glance at how usePrevious can be used in practice. Consider a React component called PreviousComponent, where we have a count state, a name state, and a button to increment the count and change the name. By incorporating usePrevious, we can effortlessly display the current count alongside its previous value, enabling users to visualize the count's changes at a glance.\n\n```javascript\nimport { useState } from \"react\"\nimport usePrevious from \"./usePrevious\"\n\nexport default function PreviousComponent() {\n    const [count, setCount] = useState(0)\n    const [name, setName] = useState(\"Sergey\")\n    const previousCount = usePrevious(count)\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e\n                {count} - {previousCount}\n            \u003c/div\u003e\n            \u003cdiv\u003e{name}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setCount(currentCount =\u003e currentCount + 1)}\u003e\n                Increment\n            \u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setName(\"John\")}\u003eChange Name\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 20. [`useRenderCount`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useRenderCount/useRenderCount.js)\n\n```javascript\nimport { useEffect, useRef } from \"react\"\n\nexport default function useRenderCount() {\n    const count = useRef(1)\n    useEffect(() =\u003e count.current++)\n    return count.current\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useRenderCount hook utilizes React's useEffect and useRef hooks to keep a count of renders. With each render, the count is incremented, providing you with real-time feedback on the component's render frequency.\n\nOne of the major advantages of using useRenderCount is its simplicity. By abstracting the logic into a reusable hook, you can easily integrate it into any component without cluttering your codebase. Additionally, it provides a clear and concise way to monitor render behavior, which can be crucial for performance optimization and debugging.\n\nThis versatile hook can be applied in various scenarios. For instance, when you're developing a complex component that exhibits unexpected rendering patterns, useRenderCount helps you pinpoint the problem by showing the exact number of renders. It is also handy for measuring the impact of certain optimizations or refactoring techniques, allowing you to assess their effectiveness.\n\nTo get started, simply import the useRenderCount hook and call it within your component. You can see its power in action by checking out the RenderCountComponent example above. By combining useRenderCount with other custom hooks like useToggle, you can build interactive components while keeping an eye on render counts.\n\n```javascript\nimport useRenderCount from \"./useRenderCount\"\nimport useToggle from \"../useToggle/useToggle\"\n\nexport default function RenderCountComponent() {\n    const [boolean, toggle] = useToggle(false)\n\n    const renderCount = useRenderCount()\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003e{boolean.toString()}\u003c/div\u003e\n            \u003cdiv\u003e{renderCount}\u003c/div\u003e\n            \u003cbutton onClick={toggle}\u003eToggle\u003c/button\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 21. [`useScript`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useScript/useScript.js)\n\n```javascript\nimport useAsync from \"../useAsync/useAsync\"\n\nexport default function useScript(url) {\n    return useAsync(() =\u003e {\n        const script = document.createElement(\"script\")\n        script.src = url\n        script.async = true\n\n        return new Promise((resolve, reject) =\u003e {\n            script.addEventListener(\"load\", resolve)\n            script.addEventListener(\"error\", reject)\n            document.body.appendChild(script)\n        })\n    }, [url])\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the significant advantages of useScript is its ability to handle script loading asynchronously. By setting the script's async attribute to true, you ensure that it won't block the rendering of your application. This improves the performance and overall user experience, especially when dealing with larger scripts or slow network connections.\n\nUseScript can be used in various scenarios. For instance, you can load external libraries like jQuery, enabling you to harness its powerful functionalities without adding bulk to your bundle. Additionally, you can load analytics scripts, social media widgets, or any other script necessary for your application's dynamic behavior.\n\nIn the example above, we see how useScript is utilized in a ScriptComponent. The useScript hook is called with the URL of the jQuery library as an argument. The hook returns the loading and error states, which can be used to display a loading spinner or an error message accordingly. Once the script is successfully loaded, the component displays the current window width using jQuery.\n\n```javascript\nimport useScript from \"./useScript\"\n\nexport default function ScriptComponent() {\n    const { loading, error } = useScript(\n        \"https://code.jquery.com/jquery-3.6.0.min.js\"\n    )\n\n    if (loading) return \u003cdiv\u003eLoading\u003c/div\u003e\n    if (error) return \u003cdiv\u003eError\u003c/div\u003e\n    return \u003cdiv\u003e{window.$(window).width()}\u003c/div\u003e\n}\n```\n\n\u003cbr /\u003e\n\n## 22. [`useStateWithHistory`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useStateWithHistory/useStateWithHistory.js)\n\n```javascript\nimport { useCallback, useRef, useState } from \"react\"\n\nexport default function useStateWithHistory(\n    defaultValue,\n    { capacity = 10 } = {}\n) {\n    const [value, setValue] = useState(defaultValue)\n    const historyRef = useRef([value])\n    const pointerRef = useRef(0)\n\n    const set = useCallback(\n        v =\u003e {\n            const resolvedValue = typeof v === \"function\" ? v(value) : v\n            if (historyRef.current[pointerRef.current] !== resolvedValue) {\n                if (pointerRef.current \u003c historyRef.current.length - 1) {\n                    historyRef.current.splice(pointerRef.current + 1)\n                }\n                historyRef.current.push(resolvedValue)\n\n                while (historyRef.current.length \u003e capacity) {\n                    historyRef.current.shift()\n                }\n                pointerRef.current = historyRef.current.length - 1\n            }\n            setValue(resolvedValue)\n        },\n        [capacity, value]\n    )\n\n    const back = useCallback(() =\u003e {\n        if (pointerRef.current \u003c= 0) return\n        pointerRef.current--\n        setValue(historyRef.current[pointerRef.current])\n    }, [])\n\n    const forward = useCallback(() =\u003e {\n        if (pointerRef.current \u003e= historyRef.current.length - 1) return\n        pointerRef.current++\n        setValue(historyRef.current[pointerRef.current])\n    }, [])\n\n    const go = useCallback(index =\u003e {\n        if (index \u003c 0 || index \u003e historyRef.current.length - 1) return\n        pointerRef.current = index\n        setValue(historyRef.current[pointerRef.current])\n    }, [])\n\n    return [\n        value,\n        set,\n        {\n            history: historyRef.current,\n            pointer: pointerRef.current,\n            back,\n            forward,\n            go,\n        },\n    ]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nAdvantages of useStateWithHistory:\n\n1. Automatic history tracking: useStateWithHistory automatically keeps track of the values you set, allowing you to access the complete history whenever you need it.\n2. Efficient memory usage: The hook utilizes a capacity parameter, ensuring that the history doesn't grow indefinitely. You can define the maximum number of historical values to keep, preventing excessive memory consumption.\n3. Time-travel functionality: With back(), forward(), and go() functions, you can seamlessly navigate through the recorded history. Travel back and forth between previous states or jump directly to a specific index, enabling powerful undo/redo or step-by-step functionality.\n\nWhere to use useStateWithHistory:\n\n1. Form management: Simplify the process of handling form inputs by providing an easy way to track changes, revert to previous values, or redo modifications.\n2. Undo/Redo functionality: Implement undo/redo functionality in your application with ease. Track state changes and allow users to navigate back and forth through their actions effortlessly.\n3. Step-by-step navigation: Use useStateWithHistory to build interactive guides or tutorials where users can navigate between different steps while preserving their progress.\n\n```javascript\nimport { useState } from \"react\"\nimport useStateWithHistory from \"./useStateWithHistory\"\n\nexport default function StateWithHistoryComponent() {\n    const [count, setCount, { history, pointer, back, forward, go }] =\n        useStateWithHistory(1)\n    const [name, setName] = useState(\"Sergey\")\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{count}\u003c/div\u003e\n            \u003cdiv\u003e{history.join(\", \")}\u003c/div\u003e\n            \u003cdiv\u003ePointer - {pointer}\u003c/div\u003e\n            \u003cdiv\u003e{name}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setCount(currentCount =\u003e currentCount * 2)}\u003e\n                Double\n            \u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setCount(currentCount =\u003e currentCount + 1)}\u003e\n                Increment\n            \u003c/button\u003e\n            \u003cbutton onClick={back}\u003eBack\u003c/button\u003e\n            \u003cbutton onClick={forward}\u003eForward\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e go(2)}\u003eGo To Index 2\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setName(\"John\")}\u003eChange Name\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 23. [`useStateWithValidation`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useStateWithValidation/useStateWithValidation.js)\n\n```javascript\nimport { useState, useCallback } from \"react\"\n\nexport default function useStateWithValidation(validationFunc, initialValue) {\n    const [state, setState] = useState(initialValue)\n    const [isValid, setIsValid] = useState(() =\u003e validationFunc(state))\n\n    const onChange = useCallback(\n        nextState =\u003e {\n            const value =\n                typeof nextState === \"function\" ? nextState(state) : nextState\n            setState(value)\n            setIsValid(validationFunc(value))\n        },\n        [validationFunc]\n    )\n\n    return [state, onChange, isValid]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useStateWithValidation hook combines the useState and useCallback hooks from React to provide an elegant solution. It takes two parameters: a validation function and an initial value. The validation function determines whether the current state is considered valid or not.\n\nOne of the key advantages of this custom hook is its flexibility. You can pass any validation function that suits your specific requirements. Whether it's checking the length of a string, ensuring a numeric value falls within a certain range, or performing more complex validations, useStateWithValidation has got you covered.\n\n```javascript\nimport useStateWithValidation from \"./useStateWithValidation\"\n\nexport default function StateWithValidationComponent() {\n    const [username, setUsername, isValid] = useStateWithValidation(\n        name =\u003e name.length \u003e 5,\n        \"\"\n    )\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003eValid: {isValid.toString()}\u003c/div\u003e\n            \u003cinput\n                type=\"text\"\n                value={username}\n                onChange={e =\u003e setUsername(e.target.value)}\n            /\u003e\n        \u003c/\u003e\n    )\n}\n```\n\nIn this example, the StateWithValidationComponent uses the useStateWithValidation hook to manage the username state. The validation function checks if the length of the username is greater than 5 characters, and the isValid variable reflects the validity of the current input.\n\n\u003cbr /\u003e\n\n## 24. [`useStorage`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useStorage/useStorage.js)\n\n```javascript\nimport { useCallback, useState, useEffect } from \"react\"\n\nexport function useLocalStorage(key, defaultValue) {\n    return useStorage(key, defaultValue, window.localStorage)\n}\n\nexport function useSessionStorage(key, defaultValue) {\n    return useStorage(key, defaultValue, window.sessionStorage)\n}\n\nfunction useStorage(key, defaultValue, storageObject) {\n    const [value, setValue] = useState(() =\u003e {\n        const jsonValue = storageObject.getItem(key)\n        if (jsonValue != null) return JSON.parse(jsonValue)\n\n        if (typeof defaultValue === \"function\") {\n            return defaultValue()\n        } else {\n            return defaultValue\n        }\n    })\n\n    useEffect(() =\u003e {\n        if (value === undefined) return storageObject.removeItem(key)\n        storageObject.setItem(key, JSON.stringify(value))\n    }, [key, value, storageObject])\n\n    const remove = useCallback(() =\u003e {\n        setValue(undefined)\n    }, [])\n\n    return [value, setValue, remove]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useStorage hook provides two convenient functions: useLocalStorage and useSessionStorage. With useLocalStorage, you can effortlessly store and retrieve data in the browser's local storage, while useSessionStorage offers the same functionality but with the session storage instead.\n\nOne of the key advantages of this custom hook is its simplicity. You can use it to store any type of data, such as strings, numbers, or even complex objects, with just a few lines of code. Additionally, useStorage handles the serialization and deserialization of data for you, so you don't have to worry about converting values to and from JSON.\n\nAnother advantage is the automatic synchronization between the stored data and the component's state. Whenever the stored data changes, the hook updates the component's state accordingly. Similarly, when the component's state changes, the hook automatically persists the new value to the storage. This bidirectional synchronization ensures that your application always reflects the latest data, making it ideal for scenarios where real-time updates are crucial.\n\nThe useStorage hook also provides a remove function, allowing you to easily delete stored values when they are no longer needed. This functionality comes in handy when implementing features like logout buttons or clearing user-specific data.\n\nYou can use the useStorage hook in a variety of scenarios. For example, imagine you have a settings panel where users can customize their preferences. By using useLocalStorage, you can easily store and retrieve these settings, ensuring that they persist across page reloads or even if the user closes and reopens the browser.\n\n```javascript\nimport { useSessionStorage, useLocalStorage } from \"./useStorage\"\n\nexport default function StorageComponent() {\n    const [name, setName, removeName] = useSessionStorage(\"name\", \"Sergey\")\n    const [age, setAge, removeAge] = useLocalStorage(\"age\", 26)\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e\n                {name} - {age}\n            \u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setName(\"John\")}\u003eSet Name\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setAge(40)}\u003eSet Age\u003c/button\u003e\n            \u003cbutton onClick={removeName}\u003eRemove Name\u003c/button\u003e\n            \u003cbutton onClick={removeAge}\u003eRemove Age\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 25. [`useTimeout`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useTimeout/useTimeout.js)\n\n```javascript\nimport { useCallback, useEffect, useRef } from \"react\"\n\nexport default function useTimeout(callback, delay) {\n    const callbackRef = useRef(callback)\n    const timeoutRef = useRef()\n\n    useEffect(() =\u003e {\n        callbackRef.current = callback\n    }, [callback])\n\n    const set = useCallback(() =\u003e {\n        timeoutRef.current = setTimeout(() =\u003e callbackRef.current(), delay)\n    }, [delay])\n\n    const clear = useCallback(() =\u003e {\n        timeoutRef.current \u0026\u0026 clearTimeout(timeoutRef.current)\n    }, [])\n\n    useEffect(() =\u003e {\n        set()\n        return clear\n    }, [delay, set, clear])\n\n    const reset = useCallback(() =\u003e {\n        clear()\n        set()\n    }, [clear, set])\n\n    return { reset, clear }\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe \"useTimeout\" hook encapsulates the logic for setting, clearing, and resetting timeouts within a React component. It takes two parameters: a callback function and a delay duration in milliseconds. Whenever the specified delay elapses, the provided callback function is executed.\n\nOne of the significant advantages of this custom hook is that it ensures the callback function remains up to date even if it changes during component re-renders. By using a useRef to store the callback reference, the hook guarantees that the latest version of the function is always called.\n\nMoreover, the \"useTimeout\" hook optimizes performance by utilizing useCallback to memoize the \"set\" and \"clear\" functions. This means that the functions are only recreated when their dependencies change, preventing unnecessary renders and enhancing efficiency.\n\nThe \"useTimeout\" hook can be utilized in various scenarios where timed actions are required. For example, in a countdown component like the \"TimeoutComponent\" showcased above, you can easily implement a timer that resets after a specific duration. By using the \"useTimeout\" hook, you can effortlessly update the countdown value and manage the timeout without worrying about complex timeout management code.\n\n```javascript\nimport { useState } from \"react\"\nimport useTimeout from \"./useTimeout\"\n\nexport default function TimeoutComponent() {\n    const [count, setCount] = useState(10)\n    const { clear, reset } = useTimeout(() =\u003e setCount(0), 1000)\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{count}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setCount(c =\u003e c + 1)}\u003eIncrement\u003c/button\u003e\n            \u003cbutton onClick={clear}\u003eClear Timeout\u003c/button\u003e\n            \u003cbutton onClick={reset}\u003eReset Timeout\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 26. [`useToggle`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useToggle/useToggle.js)\n\n```javascript\nimport { useState } from \"react\"\n\nexport default function useToggle(defaultValue) {\n    const [value, setValue] = useState(defaultValue)\n\n    function toggleValue(value) {\n        setValue(currentValue =\u003e\n            typeof value === \"boolean\" ? value : !currentValue\n        )\n    }\n\n    return [value, toggleValue]\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the main advantages of useToggle is its flexibility. With a single line of code, you can initialize the state with a default value. The toggleValue function allows you to easily toggle the state between true and false, or you can pass a boolean value directly to set the state to your desired value. This versatility makes useToggle ideal for a wide range of scenarios where toggling or switching state is required.\n\nUseToggle can be seamlessly integrated into various React components. For instance, in the provided ToggleComponent, the useToggle hook is used to manage the state of a toggle button. With a simple click, the button's state is toggled between true and false. Additionally, the hook provides buttons to directly set the value to true or false, catering to specific use cases. The resulting state is displayed dynamically, allowing for instant feedback.\n\n```javascript\nimport useToggle from \"./useToggle\"\n\nexport default function ToggleComponent() {\n    const [value, toggleValue] = useToggle(false)\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{value.toString()}\u003c/div\u003e\n            \u003cbutton onClick={toggleValue}\u003eToggle\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e toggleValue(true)}\u003eMake True\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e toggleValue(false)}\u003eMake False\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 27. [`useTranslation`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useTranslation/useTranslation.js)\n\n```javascript\nimport { useLocalStorage } from \"../useStorage/useStorage\"\nimport * as translations from \"./translations\"\n\nexport default function useTranslation() {\n    const [language, setLanguage] = useLocalStorage(\"language\", \"en\")\n    const [fallbackLanguage, setFallbackLanguage] = useLocalStorage(\n        \"fallbackLanguage\",\n        \"en\"\n    )\n\n    const translate = key =\u003e {\n        const keys = key.split(\".\")\n\n        return (\n            getNestedTranslation(language, keys) ??\n            getNestedTranslation(fallbackLanguage, keys) ??\n            key\n        )\n    }\n\n    return {\n        language,\n        setLanguage,\n        fallbackLanguage,\n        setFallbackLanguage,\n        t: translate,\n    }\n}\n\nfunction getNestedTranslation(language, keys) {\n    return keys.reduce((obj, key) =\u003e {\n        return obj?.[key]\n    }, translations[language])\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the key advantages of useTranslation is its seamless integration with the browser's localStorage. It automatically saves the selected language and fallback language preferences, so your users will see the content in their preferred language every time they visit your app.\n\nThe hook utilizes the useLocalStorage hook from the useStorage library to persist the language settings. This ensures that even if the user refreshes the page or navigates away and comes back, their language preference will be preserved.\n\nUsing useTranslation is incredibly straightforward. Simply import the hook and initialize it in your component. You'll have access to the current language, the ability to set the language, the fallback language, and the option to set the fallback language. Additionally, the hook provides a convenient translation function, t, which takes a key as input and returns the corresponding translated value.\n\nYou can use the useTranslation hook in various scenarios. Whether you're building a multi-language website, an internationalized application, or simply need to support translations in your UI components, this hook will simplify the process and make your codebase more maintainable.\n\n```javascript\nimport useTranslation from \"./useTranslation\"\n\nexport default function TranslationComponent() {\n    const { language, setLanguage, setFallbackLanguage, t } = useTranslation()\n\n    return (\n        \u003c\u003e\n            \u003cdiv\u003e{language}\u003c/div\u003e\n            \u003cdiv\u003e{t(\"hi\")}\u003c/div\u003e\n            \u003cdiv\u003e{t(\"bye\")}\u003c/div\u003e\n            \u003cdiv\u003e{t(\"nested.value\")}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setLanguage(\"sp\")}\u003eChange To Spanish\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setLanguage(\"en\")}\u003eChange To English\u003c/button\u003e\n            \u003cbutton onClick={() =\u003e setFallbackLanguage(\"sp\")}\u003eChange FB Lang\u003c/button\u003e\n        \u003c/\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 28. [`useUpdateEffect`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useUpdateEffect/useUpdateEffect.js)\n\n```javascript\nimport { useEffect, useRef } from \"react\"\n\nexport default function useUpdateEffect(callback, dependencies) {\n    const firstRenderRef = useRef(true)\n\n    useEffect(() =\u003e {\n        if (firstRenderRef.current) {\n            firstRenderRef.current = false\n            return\n        }\n        return callback()\n    }, dependencies)\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nThe useUpdateEffect hook is designed to execute a callback function only after the initial render. This behavior is particularly useful when you want to perform actions based on state changes while skipping the initial execution. By leveraging the useRef hook, useUpdateEffect tracks the first render and skips the callback during that phase.\n\nOne of the key advantages of useUpdateEffect is its simplicity. With just a few lines of code, you can enhance your React components by efficiently handling state updates. By specifying the dependencies for the hook, you can control precisely when the callback should be triggered, preventing unnecessary rendering cycles.\n\nThis custom hook can be used in various scenarios. For example, imagine you have a counter component that needs to display an alert every time the count changes, excluding the initial render. By using useUpdateEffect, you can easily achieve this behavior, improving the user experience and reducing unnecessary alerts.\n\nTo implement useUpdateEffect, simply import it into your React component and define the callback function and dependencies. The hook will take care of the rest, ensuring that the callback is executed only when necessary. It's a powerful tool that simplifies state management and enhances the performance of your React applications.\n\n```javascript\nimport { useState } from \"react\"\nimport useUpdateEffect from \"./useUpdateEffect\"\n\nexport default function UpdateEffectComponent() {\n    const [count, setCount] = useState(10)\n    useUpdateEffect(() =\u003e alert(count), [count])\n\n    return (\n        \u003cdiv\u003e\n            \u003cdiv\u003e{count}\u003c/div\u003e\n            \u003cbutton onClick={() =\u003e setCount(c =\u003e c + 1)}\u003eIncrement\u003c/button\u003e\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## 29. [`useWindowSize`](https://github.com/sergeyleschev/react-custom-hooks/blob/main/src/hooks/useWindowSize/useWindowSize.js)\n\n```javascript\nimport { useState } from \"react\"\nimport useEventListener from \"../useEventListener/useEventListener\"\n\nexport default function useWindowSize() {\n    const [windowSize, setWindowSize] = useState({\n        width: window.innerWidth,\n        height: window.innerHeight,\n    })\n\n    useEventListener(\"resize\", () =\u003e {\n        setWindowSize({ width: window.innerWidth, height: window.innerHeight })\n    })\n\n    return windowSize\n}\n```\n\n[🔝 Back to table of contents](#table-of-contents)\n\nOne of the main advantages of useWindowSize is its ease of use. By simply importing the hook and invoking it within your functional component, you gain access to an object containing the current width and height of the window. This eliminates the need for boilerplate code and allows you to focus on building dynamic and responsive interfaces.\n\nThe useEventListener hook, also included in this package, intelligently listens for window resize events. Whenever the window size changes, useWindowSize updates the state with the latest dimensions, triggering a re-render of the consuming component. This guarantees that your UI remains in sync with the user's viewing environment, resulting in a more immersive and polished user experience.\n\nThe useWindowSize hook can be used in a variety of scenarios. It's particularly handy when building responsive layouts that adapt to different screen sizes. With this hook, you can effortlessly adjust the styling, layout, or content of your components based on the available window space. Furthermore, it enables you to dynamically render or hide elements, optimize image loading, or perform any other behavior that relies on the window dimensions.\n\n```javascript\nimport useWindowSize from \"./useWindowSize\"\n\nexport default function WindowSizeComponent() {\n    const { width, height } = useWindowSize()\n\n    return (\n        \u003cdiv\u003e\n            {width} x {height}\n        \u003c/div\u003e\n    )\n}\n```\n\n\u003cbr /\u003e\n\n## Available Scripts\n\nIn the project directory, you can run:\n\n### `npm start`\n\nRuns the app in the development mode.\nOpen [http://localhost:3000](http://localhost:3000) to view it in the browser.\n\nThe page will reload if you make edits.\nYou will also see any lint errors in the console.\n\n### `npm test`\n\nLaunches the test runner in the interactive watch mode.\nSee the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.\n\n### `npm run build`\n\nBuilds the app for production to the `build` folder.\nIt correctly bundles React in production mode and optimizes the build for the best performance.\n\nThe build is minified and the filenames include the hashes.\nYour app is ready to be deployed!\n\nSee the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.\n\n### `npm run eject`\n\n**Note: this is a one-way operation. Once you `eject`, you can’t go back!**\n\nIf you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.\n\nInstead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.\n\nYou don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.\n\n# 🏆 Awards\n### Ranking #Dev: Global TOP 200 ([Certificate](https://leetcode.com/sergeyleschev/))\n\u003ca href=\"https://leetcode.com/sergeyleschev/\"\u003e\u003cimg src=\"https://github.com/sergeyleschev/sergeyleschev/blob/main/leetcode-ranking.png?raw=true\" alt=\"drawing\" width=\"410\"/\u003e\u003c/a\u003e\n\n\u003ca href=\"https://leetcode.com/sergeyleschev/\"\u003e\u003cimg src=\"https://github.com/sergeyleschev/sergeyleschev/blob/main/leetcode-medals.png?raw=true\" alt=\"drawing\" width=\"410\"/\u003e\u003c/a\u003e\n\n\u003cdiv style=\"page-break-after: always;\"\u003e\u003c/div\u003e\n\n## Contacts\n\nI have a clear focus on time-to-market and don't prioritize technical debt. And I took part in the Pre-Sale/RFX activity as a System Architect, assessment efforts for Frontend (React-TypeScript) and Backend (NodeJS-.NET-PHP-Kafka-SQL-NoSQL). And I also formed the work of Pre-Sale as a CTO from Opportunity to Proposal via knowledge transfer to Successful Delivery.\n\n🛩️ #startups #management #cto #swift #typescript #database\n\n📧 Email: [sergey.leschev@gmail.com](mailto:sergey.leschev@gmail.com)\n\n👋 LinkedIn: [https://linkedin.com/in/sergeyleschev](https://www.linkedin.com/in/sergeyleschev/)\n\n👋 Twitter: [https://twitter.com/sergeyleschev](https://twitter.com/sergeyleschev)\n\n👋 Github: [https://github.com/sergeyleschev](https://github.com/sergeyleschev)\n\n🌎 Website: [https://sergeyleschev.github.io](https://sergeyleschev.github.io)\n\n🌎 DEV Community: [https://dev.to/sergeyleschev](https://dev.to/sergeyleschev)\n\n🌎 Reddit: [https://reddit.com/user/sergeyleschev](https://reddit.com/user/sergeyleschev)\n\n🌎 Quora: [https://quora.com/sergey-leschev](https://quora.com/sergey-leschev)\n\n🌎 Medium: [https://medium.com/@sergeyleschev](https://medium.com/@sergeyleschev)\n\n🖨️ PDF: [Download](https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.pdf)\n\nALT: SIARHEI LIASHCHOU\n\n\u003cfooter\u003e\n  \u003cp style=\"font-size: 10px\"\u003e\n  \u003ca href=\"https://sergeyleschev.github.io\"\u003eleader\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eknowledge\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003equalifications\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eeducation\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003etips\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eskills\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003emultitasking\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ereferences\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003esuccess\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ework\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ejob\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003etie\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003echallenges\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eabilities\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eimpress\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eresponsibility\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003efuture\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eweeknesses\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ebenefits\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eresults\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eteam player\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003estrengths\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003einterview\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003edegress\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eexamples\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003estrengths\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eexperienced\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eproblem solver\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ecandidate\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eagency\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eobjective\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003einitiative\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eteam\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003edreams\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003econflict\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ecan-do\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003etraining\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003equestions\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ejob\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ework\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ecareer\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ecreated\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003eswift\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003etypescript\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003ejavascript\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003esql\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003enosql\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003epostgresql\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eoracle\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003esql server\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003ereact\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003eredux\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003eswiftui\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003eobjective-c\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003edevops\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eaws\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003emongodb\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003epl/sql\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003eangular\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eproject management\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003enodejs\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003enextjs\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003enestjs\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003eapi\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eagile\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eamplitude\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eanalytics\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003eappclip\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003eappstore\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003ebash\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003ecss\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ejira\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003econfluence\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003egit\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003egraphql\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003ehtml\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003ehtml5\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003emvp\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003emvvm\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003enginx\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003essh\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eprime react\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003erest\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003eteamcity\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-fullstack-roadmap.html\"\u003etypeorm\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003euikit\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003euml\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003eviper\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003ewidgets\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003excode\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io\"\u003ejson\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003elinux\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003edocker\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-system-architect-roadmap.html\"\u003emobx\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003etvOS\u003c/a\u003e, \u003ca href=\"https://sergeyleschev.github.io/sergeyleschev-ios-roadmap.html\"\u003ewatchOS\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/footer\u003e\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergeyleschev%2Freact-custom-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsergeyleschev%2Freact-custom-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsergeyleschev%2Freact-custom-hooks/lists"}