├── README.md ├── hooks.md ├── hooks ├── useBase64Encode.jsx ├── useClickInside.jsx ├── useClickOutside.jsx ├── useCopyToClipBoard.jsx ├── useCounter.jsx ├── useDialog.jsx ├── useFetch.jsx ├── useFileUpload.js ├── useHoverEvent.jsx ├── useHoverIn.jsx ├── useHoverOut.jsx ├── useInputField.jsx ├── useLocalStorage.js ├── usePagination.jsx ├── usePrevious.jsx ├── useSearchHook.js ├── useSecondsTimer.jsx ├── useSelectedList.jsx ├── useTimer.jsx ├── useToggle.jsx └── useUpdateEffect.jsx ├── index.js └── refer.md /README.md: -------------------------------------------------------------------------------- 1 | # react-custom-hooks 2 | Custom hooks in React.js that are handy in daily day to day code 3 | 4 | ## 5 | 6 | #### Custom Hooks 7 | 8 | - [useCounter](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useCounter.jsx) - React Hook to handle counter, increment and decrement 9 | - [useDialog](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useDialog.jsx) - React Hook to handle open and close dialogs 10 | - [useFetch](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useFetch.jsx) - React Hook to call apis on load with Fetch 11 | - [usePrevious](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/usePrevious.jsx) - React Hook to use previos state and props 12 | - [useToggle](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useToggle.jsx) - React Hook to handle toggle button and lists 13 | - [useInputField](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useInputField.jsx) - React Hook to use state values for input fields 14 | - [useUpdateEffect](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useClickOutside.jsx) - React Hook to call snippet ONLY-ON-UPDATE 15 | - [useCopyToClipBoard](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useCopyToClipBoard.jsx) - When you want to pass a state value and provide a copy to ClipBoard option 16 | - [useBase64Encode](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useBase64Encode.jsx) - React Hook to encode event String value to Base64 without storing text anywhere 17 | - [useSecondsTimer](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useSecondsTimer.jsx) - React Hook to use timer from n to 0 seconds 18 | - [useTimer](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useTimer.jsx) - React Hook to use timer from 0 to hh:mm:ss time runner until stopped. 19 | - [useClickInside](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useClickInside.jsx) - When you want to call a function when clicked inside the element Ex: Modal PopUp 20 | - [useClickOutside](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useClickOutside.jsx) - When you want to call a function when clicked outside the element Ex: Modal PopUp 21 | - [useHoverIn](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useHoverIn.jsx) - When you want to call a function when hovered or mouse over inside the element Ex: hovering a menu or enabling shopping card zoom 22 | - [useHoverOut](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useHoverOut.jsx) - When you want to call a function when hovered or mouse out outside the element Ex: hovering out of a menu or disabling shopping card zoom 23 | - [useHoverEvent](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useHoverEvent.jsx) - When you want to call a function when hovered or mouse out inside and outside the element Ex: hovering out of a menu or disabling shopping card zoom. 24 | [useHoverEvent](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useHoverEvent.js) hook has both [useHoverIn](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useHoverIn.js) and [useHoverOut](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/useHoverOut.js) events 25 | - [usePagination](https://github.com/sarat9/react-custom-hooks/blob/master/hooks/usePagination.jsx) - React Hook to handle numerical paginations 26 | 27 | ## 28 | ## 29 | 30 | 31 | #### Other External Hook Libraries 32 | - [awesome-react-hooks](https://github.com/glauberfc/awesome-react-hooks) - A curated list about React Hooks. 33 | - [react-use](https://github.com/streamich/react-use) - Library with Collection of essential hooks 34 | - [react-hook-form](https://github.com/react-hook-form/react-hook-form) - Handling Forms with Performant, flexible and extensible forms with easy-to-use validation. 35 | ## 36 | ## 37 | 38 | 39 | 40 | ![React Hooks](https://miro.medium.com/max/3840/1*CcTWyKvkq7IH6Of0Sq0pQQ.png)# React Hooks! 41 | 42 | 43 | ## 44 | ## 45 | 46 | #### Things To take care while creating Hooks! 47 | - **Handle Memory Leaks** : The memory leak will happen if the API server or host took some time to respond and the component was unmounted before the response was received. Though the component was unmounted, the response to the request will still be received on completion. The response will then be parsed and setData will be called. 48 | 49 | -> [How To Fix Memory Leak Issue In React Js Using Hook](https://medium.com/wesionary-team/how-to-fix-memory-leak-issue-in-react-js-using-hook-a5ecbf9becf8) 50 | 51 | 52 | 53 | 54 | ## 55 | ## 56 | 57 | 58 | Buy Me A Coffee 59 | 60 | [![GitHub followers](https://img.shields.io/github/followers/sarat9.svg?label=Follow%20@sarat9&style=social)](https://github.com/sarat9/) 61 | -------------------------------------------------------------------------------- /hooks.md: -------------------------------------------------------------------------------- 1 | 2 | Custom React Hooks Handy 3 | 4 | HOOKS: 5 | 6 | Abstract logic to Hooks. 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | Npm Libraries: 18 | 19 | 20 | -------------------------------------------------------------------------------- /hooks/useBase64Encode.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | 3 | /** 4 | * @function useBase64Encode 5 | * @description React Hook to encode event String value to Base64 without storing text anywhere 6 | * @param {any} value 7 | * @returns {any} encoded value and function to pass event 8 | * @author Sarat Chandra Ejjapureddi 9 | */ 10 | export default function useBase64Encode(defaultValue = '') { 11 | const [value, setValue] = useState(btoa(defaultValue)) 12 | 13 | const encodeValue = (e) => { 14 | if (e) { 15 | // btoa() Encodes String to Base64 16 | setValue(btoa(e.target.value)) 17 | } 18 | } 19 | 20 | const decodeValue = (e) => { 21 | if (e) { 22 | // atob() Encodes Base64 to String 23 | setValue(atob(e.target.value)) 24 | } 25 | } 26 | return [value, encodeValue] 27 | } 28 | 29 | 30 | 31 | 32 | 33 | 34 | /* 35 | * What is Base64? 36 | * https://infosecwriteups.com/base64-explained-17cd8864da02 37 | */ 38 | -------------------------------------------------------------------------------- /hooks/useClickInside.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from '../../../../../Users/scejjapu/AppData/Local/Microsoft/TypeScript/2.9/node_modules/@types/react' 2 | 3 | 4 | 5 | /** 6 | * @function useClickInside 7 | * @param {any} elementRef 8 | * @param {any} callback 9 | * @returns {any} 10 | * @description When you want to call a function when clicked inside the element Ex: Modal PopUp 11 | * Pass the callback with useCallBack in your function since it's functionality always remains same for better performance. 12 | * @author Sarat Chandra Ejjapureddi 13 | */ 14 | export default function useClickInside(elementRef, callback) { 15 | React.useEffect(() => { 16 | const handleClickInside = (event) => { 17 | event.preventDefault() 18 | if (elementRef && elementRef.current && elementRef.current.contains(event.target)) { 19 | // Call Callback only if event happens inside element or descendent elements 20 | callback() 21 | } 22 | return 23 | } 24 | document.addEventListener('click', handleClickInside, true) 25 | return () => { 26 | document.removeEventListener('click', handleClickInside, true) 27 | } 28 | }, [elementRef, callback]) 29 | } 30 | 31 | 32 | /** 33 | * @function useClickInside 34 | * @param {any} elementRef 35 | * @param {any} callback 36 | * @returns {any} 37 | * @description When you want to call a function when clicked inside the element Ex: Modal PopUp 38 | * Use this function rather than above when you are sure you wont be changing the callback. 39 | * You then don't need to pass the callback with useCallback for performance. 40 | */ 41 | export function useClickInside2(elementRef, callback) { 42 | const callbackRef = useRef(callback) 43 | React.useEffect(() => { 44 | const handleClickInside = (event) => { 45 | event.preventDefault() 46 | if (elementRef && elementRef.current && elementRef.current.contains(event.target)) { 47 | // Call Callback only if event happens inside element or descendent elements 48 | callbackRef.current() 49 | } 50 | return 51 | } 52 | document.addEventListener('click', handleClickInside, true) 53 | return () => { 54 | document.removeEventListener('click', handleClickinside, true) 55 | } 56 | }, [elementRef, callback]) 57 | } -------------------------------------------------------------------------------- /hooks/useClickOutside.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | 4 | 5 | /** 6 | * @function useClickOutside 7 | * @param {any} elementRef 8 | * @param {any} callback 9 | * @returns {any} 10 | * @description When you want to call a function when clicked outside the element Ex: Modal PopUp 11 | * @author Sarat Chandra Ejjapureddi 12 | * Pass the callback with useCallBack in your function since it's functionality always remains same for better performance. 13 | */ 14 | export default function useClickOutside(elementRef, callback) { 15 | React.useEffect(() => { 16 | const handleClickOutside = (event) => { 17 | event.preventDefault() 18 | if (elementRef && elementRef.current && !elementRef.current.contains(event.target)) { 19 | // Call Callback only if event happens outside element or descendent elements 20 | callback() 21 | } 22 | return 23 | } 24 | document.addEventListener('click', handleClickOutside, true) 25 | return () => { 26 | document.removeEventListener('click', handleClickOutside, true) 27 | } 28 | }, [elementRef, callback]) 29 | } 30 | 31 | 32 | /** 33 | * @function useClickOutside 34 | * @param {any} elementRef 35 | * @param {any} callback 36 | * @returns {any} 37 | * @description When you want to call a function when clicked outside the element Ex: Modal PopUp 38 | * Use this function rather than above when you are sure you wont be changing the callback. 39 | * You then don't need to pass the callback with useCallback for performance. 40 | */ 41 | export function useClickOutside2(elementRef, callback) { 42 | const callbackRef = useRef(callback) 43 | React.useEffect(() => { 44 | const handleClickOutside = (event) => { 45 | event.preventDefault() 46 | if (elementRef && elementRef.current && !elementRef.current.contains(event.target)) { 47 | // Call Callback only if event happens outside element or descendent elements 48 | callbackRef.current() 49 | } 50 | return 51 | } 52 | document.addEventListener('click', handleClickOutside, true) 53 | return () => { 54 | document.removeEventListener('click', handleClickOutside, true) 55 | } 56 | }, [elementRef, callback]) 57 | } -------------------------------------------------------------------------------- /hooks/useCopyToClipBoard.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | 4 | 5 | /** 6 | * @function useCopyToClipboard 7 | * @param {any} text 8 | * @returns {[Function, Function]} 9 | * @description When you want to pass a state value and provide a copy to ClipBoard option 10 | * @author Sarat Chandra Ejjapureddi 11 | * 12 | * When you want to pass a state value and provide a copy to ClipBoard option. 13 | * Whenever a state value is passed as parameter, invoking the call function will set the value in clipboard 14 | */ 15 | export default function useCopyToClipboard(text) { 16 | 17 | const copyToClipboard = (str) => { 18 | const el = document.createElement('textarea'); 19 | el.value = str; 20 | el.setAttribute('readonly', ''); 21 | el.style.position = 'absolute'; 22 | el.style.left = '-9999px'; 23 | document.body.appendChild(el); 24 | const selected = 25 | document.getSelection().rangeCount > 0 26 | ? document.getSelection().getRangeAt(0) 27 | : false; 28 | el.select(); 29 | const success = document.execCommand('copy'); 30 | document.body.removeChild(el); 31 | if (selected) { 32 | document.getSelection().removeAllRanges(); 33 | document.getSelection().addRange(selected); 34 | } 35 | return success; 36 | }; 37 | 38 | const [copied, setCopied] = React.useState(false); 39 | 40 | const copy = React.useCallback(() => { 41 | if (!copied) setCopied(copyToClipboard(text)); 42 | }, [text]); 43 | 44 | React.useEffect(() => () => setCopied(false), [text]); 45 | 46 | return [copied, copy]; 47 | }; -------------------------------------------------------------------------------- /hooks/useCounter.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | 4 | /** 5 | * @function useCounter 6 | * @description React Hook to handle counter, increment and decrement 7 | * @returns {Array:Function} : [counter, increment, decrement] 8 | * @author Sarat Chandra Ejjapureddi 9 | */ 10 | function useCounter(defaultValue=0) { 11 | const [counter, setCounter] = React.useState(defaultValue); 12 | 13 | const increment = () => { 14 | setCounter(counter+1); 15 | }; 16 | 17 | const decrement = () => { 18 | setCounter(counter-1); 19 | }; 20 | return [counter, increment, decrement] 21 | } 22 | 23 | export default useCounter -------------------------------------------------------------------------------- /hooks/useDialog.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | 4 | /** 5 | * @function useDialogHook 6 | * @description React Hook to handle open and close dialogs 7 | * @returns {Array:Function} : [open, handleClickOpen, handleClose] 8 | * @author Sarat Chandra Ejjapureddi 9 | */ 10 | function useDialogHook() { 11 | const [open, setOpen] = React.useState(false); 12 | 13 | const handleClickOpen = () => { 14 | setOpen(true); 15 | }; 16 | 17 | const handleClose = () => { 18 | setOpen(false); 19 | }; 20 | return [open, handleClickOpen, handleClose] 21 | } 22 | 23 | export default useDialogHook -------------------------------------------------------------------------------- /hooks/useFetch.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | 4 | 5 | const initialOptions = { 6 | method: 'GET', // *GET, POST, PUT, DELETE, etc. 7 | mode: 'cors', // no-cors, *cors, same-origin 8 | cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached 9 | credentials: 'same-origin', // include, *same-origin, omit 10 | headers: { 11 | 'Content-Type': 'application/json' 12 | // 'Content-Type': 'application/x-www-form-urlencoded', 13 | }, 14 | redirect: 'follow', // manual, *follow, error 15 | referrerPolicy: 'no-referrer', // no-referrer, *no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url 16 | // body: JSON.stringify(data) // body data type must match "Content-Type" header 17 | }; 18 | 19 | /** 20 | * @function useFetch 21 | * @description React Hook to call apis on load with Fetch . 22 | * componentMounted flag to avaoid memory leak 23 | * @param {string} url 24 | * @param {Object} options 25 | * @returns {Object} { response, error, loading } 26 | * @author Sarat Chandra Ejjapureddi 27 | * @example data = useFetch('') 28 | */ 29 | export default function useFetch(url, options = initialOptions) { 30 | const [response, setResponse] = useState(null) 31 | const [error, setError] = useState(null) 32 | const [loading, setLoading] = useState(false) 33 | useEffect(() => { 34 | let componentMounted = true; 35 | const fetchData = async () => { 36 | 37 | try { 38 | setLoading(true) 39 | const res = await fetch(url, options) 40 | const json = await res.json() 41 | if(componentMounted){ 42 | setResponse(json) 43 | } 44 | } catch (err) { 45 | setLoading(false) 46 | setError(err) 47 | } 48 | finally { 49 | setLoading(false) 50 | } 51 | } 52 | fetchData() 53 | return () => { 54 | componentMounted = false; 55 | } 56 | }, []) 57 | return { response, error, loading } 58 | } -------------------------------------------------------------------------------- /hooks/useFileUpload.js: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | 3 | /** 4 | * @function useFileUpload 5 | * @description React Hook to use state values for file uploads 6 | * @returns [selectedFile, handleFileInputChange, fileDetails] 7 | * @author Sarat Chandra Ejjapureddi 8 | */ 9 | export default function useFileUpload() { 10 | const [selectedFile, setSelectedFile] = useState(null); 11 | const [fileDetails, setFileDetails] = useState(null); 12 | 13 | 14 | const handleFileInputChange = (e) => { 15 | const fileData = e.target.files[0]; 16 | const { name, type, size } = fileData; 17 | setSelectedFile(fileData); 18 | setFileDetails({ name, type, size }); 19 | }; 20 | 21 | return [selectedFile, handleFileInputChange, fileDetails] 22 | } -------------------------------------------------------------------------------- /hooks/useHoverEvent.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | 4 | 5 | /** 6 | * @function useHoverEvent 7 | * @param {any} elementRef 8 | * @param {any} hoveredCallback - when hovered on element 9 | * @param {any} hoveredOutCallback - when hovered/mouse out from the element after hover 10 | * @returns {any} 11 | * @description When you want to call a function when hovered inside the element 12 | * Ex: Hovering on Shopping Card should detect the event call a function to scroll other pics or highlighting 13 | * Pass the callback with useCallBack in your function since it's functionality always remains same for better performance. 14 | * @author Sarat Chandra Ejjapureddi 15 | */ 16 | export default function useHoverEvent(elementRef, hoveredCallback, hoveredOutCallback) { 17 | React.useEffect(() => { 18 | const handleHoverInside = (event) => { 19 | event.preventDefault() 20 | if (elementRef && elementRef.current && elementRef.current.contains(event.target)) { 21 | // Call Callback only if event happens inside element or descendent elements 22 | hoveredCallback() 23 | } 24 | return 25 | } 26 | const handleHoverOut = (event) => { 27 | event.preventDefault() 28 | if (elementRef && elementRef.current && elementRef.current.contains(event.target)) { 29 | // Call Callback only if event happens inside element or descendent elements 30 | hoveredOutCallback() 31 | } 32 | return 33 | } 34 | 35 | // Calls when an elements is hovered 36 | document.addEventListener('mouseover', handleHoverInside, true) 37 | // Calls when an elements is hovered and then hovered out (mouseout) of that element 38 | document.addEventListener('mouseout', handleHoverOut, true) 39 | return () => { 40 | document.removeEventListener('mouseover', handleHoverInside, true) 41 | document.removeEventListener('mouseout', handleHoverOut, true) 42 | } 43 | }, [elementRef, hoveredCallback, hoveredOutCallback]) 44 | } -------------------------------------------------------------------------------- /hooks/useHoverIn.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | 4 | 5 | /** 6 | * @function useHoverIn 7 | * @param {any} elementRef 8 | * @param {any} callback 9 | * @returns {any} 10 | * @description When you want to call a function when hovered inside the element 11 | * Ex: Hovering on Shopping Card should detect the event call a function to scroll other pics or highlighting 12 | * Pass the callback with useCallBack in your function since it's functionality always remains same for better performance. 13 | * @author Sarat Chandra Ejjapureddi 14 | */ 15 | export default function useHoverIn(elementRef, callback) { 16 | React.useEffect(() => { 17 | const handleHoverInside = (event) => { 18 | event.preventDefault() 19 | if (elementRef && elementRef.current && elementRef.current.contains(event.target)) { 20 | // Call Callback only if event happens inside element or descendent elements 21 | callback() 22 | } 23 | return 24 | } 25 | document.addEventListener('mouseover', handleHoverInside, true) 26 | return () => { 27 | document.removeEventListener('mouseover', handleHoverInside, true) 28 | } 29 | }, [elementRef, callback]) 30 | } -------------------------------------------------------------------------------- /hooks/useHoverOut.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | /** 4 | * @function useHoverOut 5 | * @param {any} elementRef 6 | * @param {any} callback 7 | * @returns {any} 8 | * @description When you want to call a function when hovered inside the element 9 | * Ex: Hovering on Shopping Card should detect the event call a function to scroll other pics or highlighting 10 | * Pass the callback with useCallBack in your function since it's functionality always remains same for better performance. 11 | * @author Sarat Chandra Ejjapureddi 12 | */ 13 | export default function useHoverOut(elementRef, callback) { 14 | React.useEffect(() => { 15 | const handleHoverOut = (event) => { 16 | event.preventDefault() 17 | if (elementRef && elementRef.current && elementRef.current.contains(event.target)) { 18 | // Call Callback only if event happens inside element or descendent elements 19 | callback() 20 | } 21 | return 22 | } 23 | document.addEventListener('mouseout', handleHoverOut, true) 24 | return () => { 25 | document.removeEventListener('mouseout', handleHoverOut, true) 26 | } 27 | }, [elementRef, callback]) 28 | } -------------------------------------------------------------------------------- /hooks/useInputField.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | 3 | /** 4 | * @function useInputField 5 | * @description React Hook to use state values for input fields 6 | * @param {any} defaultValue 7 | * @param {boolean} specialCharsAllow 8 | * @returns {any} 9 | * @author Sarat Chandra Ejjapureddi 10 | */ 11 | export default function useInputField(defaultValue = '', specialCharsAllow=true) { 12 | const [value, setValue] = useState(defaultValue) 13 | 14 | const handleInputValue = (e) => { 15 | if (e) { 16 | let val = e.target.value 17 | if(!specialCharsAllow){ 18 | val = val.replace(/[^\w\s]/gi, "") 19 | } 20 | setValue(e.target.value) 21 | } 22 | } 23 | 24 | return [value, setValue, handleInputValue] 25 | } 26 | 27 | 28 | 29 | // Regex Expressions to handle Special Characters depending o n UseCase 30 | /* 31 | * Replaces all Special Characters: 32 | * val.replace(/[^\w\s]/gi, "") 33 | * Replaces all Special Characters Except Comma(,): 34 | * val.replace(/[^\w\s,]/gi, "") 35 | * Allows only Numeric Digits and Comma(,): 36 | * val.replace(/[^0-9\.,]/g, "") 37 | * 38 | **/ -------------------------------------------------------------------------------- /hooks/useLocalStorage.js: -------------------------------------------------------------------------------- 1 | import { useState, useEffect } from 'react'; 2 | 3 | // Hook to get and set values in localStorage 4 | export function useLocalStorage(key, initialValue=null) { 5 | 6 | const [storedValue, setStoredValue] = useState(() => { 7 | try { 8 | const item = window.localStorage.getItem(key); 9 | return item ? JSON.parse(item) : initialValue; 10 | } catch (error) { 11 | console.log(error); 12 | return initialValue; 13 | } 14 | }); 15 | 16 | const setValue = value => { 17 | try { 18 | const valueToStore = value instanceof Function ? value(storedValue) : value; 19 | setStoredValue(valueToStore); 20 | window.localStorage.setItem(key, JSON.stringify(valueToStore)); 21 | } catch (error) { 22 | console.log(error); 23 | } 24 | }; 25 | 26 | return [storedValue, setValue]; 27 | } 28 | -------------------------------------------------------------------------------- /hooks/usePagination.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState } from 'react' 2 | 3 | 4 | /** 5 | * @function usePagination 6 | * @description React Hook to handle page, increment, decrement and setPage 7 | * @returns {Array:Function} : [page, increment, decrement, setPage] 8 | * @author Sarat Chandra Ejjapureddi 9 | */ 10 | function usePagination(defaultValue=1) { 11 | const [page, setPage] = React.useState(defaultValue); 12 | 13 | const onToNextPage = () => { 14 | setPage(page+1); 15 | }; 16 | 17 | const onToPreviousPage = () => { 18 | setPage(page-1); 19 | }; 20 | 21 | const handlePage = (e,value) => { 22 | e.preventDefault() 23 | setPage(value); 24 | }; 25 | 26 | const resetPage = () => { 27 | setPage(defaultValue); 28 | } 29 | 30 | return [page, handlePage, resetPage, onToNextPage, onToPreviousPage, setPage] 31 | } 32 | 33 | export default usePagination -------------------------------------------------------------------------------- /hooks/usePrevious.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | /** 4 | * @function usePrevious 5 | * @description React Hook to use previos state and props 6 | * @param {any} value 7 | * @returns {any} previousValue 8 | * @author Sarat Chandra Ejjapureddi 9 | */ 10 | export default function usePrevious(value) { 11 | const previousValue = useRef(value) 12 | useEffect(() => { 13 | previousValue.current = value; 14 | }) 15 | 16 | // Return previous value (happens before update in useEffect above) 17 | return previousValue.current 18 | } -------------------------------------------------------------------------------- /hooks/useSearchHook.js: -------------------------------------------------------------------------------- 1 | import { func } from "prop-types"; 2 | import React, { useState, useEffect, useCallback, useRef } from "react"; 3 | 4 | /** 5 | * @function useSearch 6 | * @description React Hook to use state values for input fields 7 | * @param {any} defaultValue 8 | * @param {int} debounceDelay 9 | * @returns {any} 10 | * @author Sarat Chandra Ejjapureddi 11 | */ 12 | export default function useSearch(defaultValue = "", debounceDelay = 500) { 13 | const [value, setValue] = useState(defaultValue); 14 | 15 | const handleInputValue = (e) => { 16 | if (e) { 17 | e.preventDefault(); 18 | let val = e.target.value; 19 | setValue(val); 20 | } 21 | }; 22 | 23 | const debouncedFun = debounce(handleInputValue, debounceDelay); 24 | return [value, setValue, debouncedFun]; 25 | } 26 | 27 | 28 | function debounce(fn, wait) { 29 | let timeout; 30 | return function () { 31 | clearTimeout(timeout); 32 | const args = arguments; 33 | timeout = setTimeout(() => { 34 | fn(...args); 35 | }, wait); 36 | }; 37 | } 38 | 39 | function useDebounce(callback, delay = 500) { 40 | const debounceRef = useRef(); 41 | let debouncedCallback = function(){ 42 | 43 | if (debounceRef.current) { 44 | clearTimeout(debounceRef.current); 45 | } 46 | 47 | debounceRef.current = setTimeout(()=> { 48 | const args = arguments; 49 | callback(...args); 50 | }, delay); 51 | }; 52 | 53 | return debouncedCallback; 54 | } 55 | 56 | -------------------------------------------------------------------------------- /hooks/useSecondsTimer.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | 3 | 4 | /** 5 | * @function useSecondsTimer 6 | * @description React Hook to use timer from n to 0 seconds 7 | * @param {any} defaultClock default time to start timer 8 | * @returns {any} [time, playing, togglePlayPause, handleReset] 9 | * @author Sarat Chandra Ejjapureddi 10 | */ 11 | export default function useSecondsTimer(defaultClock = 0) { 12 | const [time, setTime] = useState(defaultClock); 13 | const [playing, setPlaying] = useState(true); 14 | 15 | const tick = (e) => { 16 | e && e.preventDefault() 17 | if (time > 0 && playing) { 18 | setTime(time - 1) 19 | } 20 | } 21 | 22 | const handleReset = (e) => { 23 | e && e.preventDefault() 24 | setTime(defaultClock) 25 | } 26 | 27 | const togglePlayPause = (e) => { 28 | e && e.preventDefault() 29 | setPlaying(!playing) 30 | } 31 | 32 | useEffect(() => { 33 | let timerId = setInterval(tick, 1000); 34 | return () => clearInterval(timerId); 35 | }, [time, playing]) 36 | 37 | 38 | return [time, playing, togglePlayPause, handleReset] 39 | } 40 | 41 | -------------------------------------------------------------------------------- /hooks/useSelectedList.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useEffect } from 'react' 2 | 3 | /** 4 | * @function useSelectedList 5 | * @description React Hook to use List where we can select or unselect list of items 6 | * @param {any} value 7 | * @returns {any} 8 | * @author Sarat Chandra Ejjapureddi 9 | */ 10 | export default function useSelectedList(defaultList = [], uniqueValue) { 11 | 12 | 13 | //-------------------IN Progress 14 | 15 | const [list, setList] = useState(defaultList) 16 | const [uniqueValue, setUniqueValue] = useState(uniqueValue) 17 | const [selectedList, setSelectedList] = useState(uniqueValue) 18 | 19 | 20 | 21 | 22 | const handleInputValue = (e) => { 23 | if (e) { 24 | setValue(e.target.value) 25 | } 26 | } 27 | 28 | return [list] 29 | } -------------------------------------------------------------------------------- /hooks/useTimer.jsx: -------------------------------------------------------------------------------- 1 | 2 | import React, { useState, useEffect } from 'react' 3 | 4 | 5 | /** 6 | * @function useTimer 7 | * @description React Hook to use timer in format hh:mm:ss 8 | * @param {any} defaultClock default time to start timer 9 | * @param {any} defaultRunningStatus default runing status of timer 10 | * @returns {any} [time, isTimerRunning, togglePlayPause, handleReset] 11 | * You can use the values timer, isTimerRunning, toggleTimer, resetTimer 12 | * @author Sarat Chandra Ejjapureddi 13 | */ 14 | export default function useTimer(defaultClock = 0, defaultRunningStatus =false) { 15 | const [time, setTime] = useState(defaultClock); 16 | const [isTimerRunning, setTimerRunning] = useState(defaultRunningStatus); 17 | const [timerData, setTimerData] = useState('HH:MM:SS'); 18 | 19 | const tick = (e) => { 20 | e && e.preventDefault() 21 | if (time >= 0 && isTimerRunning) { 22 | setTime(time + 1) 23 | } 24 | } 25 | 26 | const handleReset = (e) => { 27 | e && e.preventDefault() 28 | setTime(defaultClock) 29 | } 30 | 31 | const togglePlayPause = (e) => { 32 | e && e.preventDefault() 33 | setTimerRunning(!isTimerRunning) 34 | } 35 | 36 | const secondsToHMSText = (seconds) => { 37 | // Use this function if you want to get timer data in text 38 | // example - '2 hours, 44 minutes, 49 seconds' 39 | seconds = Number(seconds); 40 | var h = Math.floor(seconds / 3600); 41 | var m = Math.floor(seconds % 3600 / 60); 42 | var s = Math.floor(seconds % 3600 % 60); 43 | 44 | var hDisplay = h > 0 ? h + (h == 1 ? " hour, " : " hours, ") : ""; 45 | var mDisplay = m > 0 ? m + (m == 1 ? " minute, " : " minutes, ") : ""; 46 | var sDisplay = s > 0 ? s + (s == 1 ? " second" : " seconds") : ""; 47 | return hDisplay + mDisplay + sDisplay; 48 | } 49 | 50 | const secondsToHMS = (seconds) => { 51 | console.log(seconds) 52 | seconds = Number(seconds); 53 | var h = Math.floor(seconds / 3600); 54 | var m = Math.floor(seconds % 3600 / 60); 55 | var s = Math.floor(seconds % 3600 % 60); 56 | 57 | var hDisplay = h > 0 ? String(h).padStart(2, '0') : "00"; 58 | var mDisplay = m > 0 ? String(m).padStart(2, '0') : "00"; 59 | var sDisplay = s > 0 ? String(s).padStart(2, '0') : "00"; 60 | // example - '2 hours, 44 minutes, 49 seconds' 61 | return hDisplay + ':' + mDisplay + ':' + sDisplay; 62 | } 63 | 64 | useEffect(() => { 65 | setTimerData(secondsToHMS(time)) 66 | let timerId = setInterval(tick, 1000); 67 | return () => clearInterval(timerId); 68 | }, [time, isTimerRunning]) 69 | 70 | 71 | return [timerData, isTimerRunning, togglePlayPause, handleReset] 72 | } -------------------------------------------------------------------------------- /hooks/useToggle.jsx: -------------------------------------------------------------------------------- 1 | import React, { useState, useCallback } from 'react' 2 | 3 | /** 4 | * @function useToggleHook 5 | * @description React Hook to handle toggle button and lists 6 | * @returns {Array:Function} : [open, handleClickOpen, handleClose] 7 | */ 8 | function useToggle(defaultState) { 9 | const [open, setOpen] = useState(defaultState||false); 10 | 11 | const toggleFun = useCallback((e) => { 12 | setOpen(!open); 13 | e.stopPropagation(); 14 | },[open]); 15 | 16 | return [open, toggleFun] 17 | } 18 | 19 | export default useToggle -------------------------------------------------------------------------------- /hooks/useUpdateEffect.jsx: -------------------------------------------------------------------------------- 1 | import React, { useRef, useEffect } from 'react' 2 | 3 | 4 | /** 5 | * @function useUpdateEffect 6 | * @description React Hook to call snippet ONLY-ON-UPDATE 7 | * Refrence: https://stackoverflow.com/questions/55075604/react-hooks-useeffect-only-on-update 8 | * 9 | * @param {Function} effect 10 | * @param {Array} dependencies 11 | * @returns {Function} cleanUpFunction() 12 | * @author Sarat Chandra Ejjapureddi 13 | */ 14 | export default function useUpdateEffect(effect, dependencies) { 15 | const isInitialMount = useRef(true); 16 | let cleanUpFunction = function () { } 17 | useEffect(() => { 18 | if (isInitialMount.current) { 19 | isInitialMount.current = false; 20 | } else { 21 | cleanUpFunction = effect() || cleanUpFunction 22 | } 23 | return () => { 24 | cleanUpFunction() 25 | // if (!isInitialMount.current) { 26 | // isInitialMount.current = true; 27 | // } 28 | } 29 | }, dependencies); 30 | } -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sarat9/react-custom-hooks/5c30892fe540597f1df3db43b56dc43c72dd44e8/index.js -------------------------------------------------------------------------------- /refer.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Helpful Links: 4 | 5 | - https://usehooks.com/ 6 | - https://www.30secondsofcode.org/react/t/hooks/p/1 7 | - https://github.com/beizhedenglong/react-hooks-lib 8 | - https://github.com/react-hook-form/react-hook-form 9 | --------------------------------------------------------------------------------