Skip to content

Repository files navigation

ReactHooks

A collection of useful custom React hooks.

To install this package run:

npm i -D @rs1/react-hooks

Here you can view a working example of every hook, with walk through sample code:
Demo site

Available hooks

  • useAgentParser
    Use it to parse the current user-agent string and to detect if the device is touch enabled.

  • useAutoIdle
    Use it to update your UI when the user isn't interacting with a component.

  • useDynamicRef
    Use it to keep a dynamic – auto-updating or manual-updating – reference to a DOM node.

  • useFullScreen
    Use it to gain access to the native Full Screen API.

  • useKeyAction
    Use it to link a callback to a key press, updating it when any dependencies change.

  • useKeyLinkedRef
    Use it to easily let a keyboard key press simulate the click on a DOM node.

  • useListener
    Use it to attach an event listener to a DOM node, updating it when the DOM node or any dependencies change.

  • useMediaQuery
    Use it to update your UI based on the viewport size of the browser.

  • useRectRef
    Use it to keep a reference to the bounding client rect of a DOM node.

  • useRefEffect
    Use it in combination with useDynamicRef to react to a DOM node change.

  • useSliderRef
    Use it to transform any DOM node in a horizontal slider, handling touch and drag events

useAgentParser

Useful to parse the current user-agent string and to detect if the device is touch enabled.

How to use it in your React component:

importReactfrom'react'import{useAgentParser}from'@rs1/react-hooks'exportdefault(props)=>{const{
isTouch,OS: {name: osName,version: osVersion,},browser: {name: browserName,version: browserVersion,major: browserMajor,},
agent,}=useAgentParser()return(<div><h3>{`${osName} (v${osVersion})`}</h3>{`You're ${isTouch ? 'touching' : 'surfing'} the web with ${browserName}${browserMajor} (v${browserVersion}), what a wonderful browser!`}<hr/><pre>{agent}</pre></div>)}

useAutoIdle

Useful if you need to update your UI when the user isn't interacting with a component.

How to use it in your React component:

exportdefaultprops=>{constnode=useRef()const[isIdle]=useAutoIdle(// Which node should be watched?node?.current,{// What callback should be fired on change?callback: idle=>console.log(`The watched node is now ${idle ? 'idle' : 'active'}`),// How many seconds shoud be waited before going to idle?wait: 5,// Is there a condition that should be true before going to idle?condition: true,// Is the node initially idle?initial: false,})return(<divref={node}style={{minWidth: '300px',minHeight: '300px',background: isIdle ? 'red' : 'blue',color: '#ffffff',padding: '15px',}}>
This node reacts to your mouse movements. After 5 seconds that you
stopped interacting, it'll go idle.
<hr/>{`This node is currently ${isIdle ? 'idle' : 'active'}`}</div>)}

useDynamicRef

Useful to keep a dynamic – auto-updating or manual-updating – reference to a DOM node.

How to use it in your React component:

importReact,{useEffect,useRef}from'react'import{useDynamicRef}from'@rs1/react-hooks'exportdefault({ url, isVideo, ...props})=>{const[media,mediaRef/* , updateMediaRef */]=useDynamicRef(/* Initial value: */null,/* Require manual-update: */false)useEffect(()=>{console.log(`The media ref tag is: ${media?.tagName}`)},[media])/* Comparison with the standard useRef hook */conststdRef=useRef()useEffect(()=>{console.log(`The standard ref tag is: ${media?.tagName}`)},[stdRef])return(<div><h6>
useDynamicRef - Current tag: {media?.tagName||'undefined'}</h6>{isVideo ? (<videoref={mediaRef}src={url}controlsstyle={{width: '100%'}}/>) : (<audioref={mediaRef}src={url}controlsstyle={{width: '100%'}}/>)}<hr/><h6>useRef - Current tag: {stdRef?.tagName||'undefined'}</h6>{isVideo ? (<videoref={stdRef}src={url}controlsstyle={{width: '100%'}}/>) : (<audioref={stdRef}src={url}controlsstyle={{width: '100%'}}/>)}</div>)}

useFullScreen

Useful to gain access to the native Full Screen API.

How to use it in your React component:

importReact,{useRef}from'react'import{useFullScreen}from'@rs1/react-hooks'exportdefaultprops=>{constcontainerRef=useRef()constvideoRef=useRef()const{// request,// exit,
toggle,
isActive,
isSupported,}=useFullScreen({onChange: ()=>console.log(`Full screen status changed`),onError: ()=>console.log(`Full screen request failed`),})constbbbMovie='http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4'return(<div><divref={containerRef}style={{width: '100%',height: '100%',minHeight: '200px',position: 'relative',background: isActive ? '#000000' : '#ffffff',}}><videoref={videoRef}style={{width: '100%',height: '100%'}}controls><sourcesrc={bbbMovie}type='video/mp4'/></video>{isSupported(containerRef,videoRef)&&(<buttononClick={()=>{/* We can feed two DOM nodes to the API, the first is the one we want to be full screen, the second is an optional media element to be set full screen on the WebKit mobile version that doesn't support the full screen API for normal DOM nodes. */toggle(containerRef,videoRef)/* This is the same as: if (isActive) exit() else request(containerRef, videoRef) */}}style={{position: 'absolute',top: '25px',right: '25px',}}>{`${isActive ? 'Exit' : 'Enter'} full screen`}</button>)}</div></div>)}

useKeyAction

Useful to link a callback to a key press, updating it when any dependencies change.

How to use it in your React component:

importReact,{useCallback}from'react'import{useKeyAction}from'@rs1/react-hooks'exportdefault(props)=>{constcallback=()=>alert(`'K' key pressed!`)useKeyAction(/* 75 is the code for the 'K' key */75,/* The callback to fire when the key is pressed */callback,/* Optional array: dependencies */[],/* Optional boolean: whether or not should listen * to key press events coming from input elements * (input, button, select, textarea) */false)return(<div><h5>Press 'K' and you'll see!</h5></div>)}

useKeyLinkedRef

Useful to easily let a keyboard key press simulate the click on a DOM node.

How to use it in your React component:

importReact,{useCallback}from'react'import{useKeyLinkedRef}from'@rs1/react-hooks'exportdefault(props)=>{/* 75 is the code for the 'K' key */constbuttonRef=useKeyLinkedRef(75)consthandleClick=useCallback(e=>{console.log(`Received click on: "${e?.currentTarget?.id}"`)},[])return(<div><buttonref={buttonRef}onClick={handleClick}id="key-linked-button">
Click me or press 'K'
</button><h5>...and keep an eye on the console!</h5></div>)}

useListener

Useful to attach an event listener to a DOM node, updating it when the DOM node or any dependencies change.

How to use it in your React component:

importReact,{useState,useCallback,useRef}from'react'import{useListener}from'@rs1/react-hooks'exportdefaultprops=>{constsectionRef=useRef()const[counter,setCounter]=useState(0)useListener(sectionRef?.current,'click',()=>console.log(`The counter is: ${counter}`),[counter])consthandleClick=useCallback(()=>{setCounter(counter=>counter+1)},[])return(<div><p>Click the red section and check the console!</p><buttononClick={handleClick}>Increase counter ({counter})</button><hr/><divref={sectionRef}style={{padding: '15px',background: 'red',color: '#ffffff'}}>
I've used the useListener hook.
</div></div>)}

useMediaQuery

Useful to update your UI based on the viewport size of the browser.

How to use it in your React component:

importReactfrom'react'import{useMediaQuery}from'@rs1/react-hooks'exportdefaultprops=>{/* * You can pass an array of breakpoint widths * to this custom hook, it'll return an array * of boolean values indicating if that size * is supported. Additionally an extra parameter * is returned to signal if no width is supported. * The widths must be passed in descending order. */const[desktop,laptop,tablet,smartphone,none]=useMediaQuery([1920,1024,768,414])/* * Alternatively, you can pass an object of * breakpoint widths for every key to this custom * hook, it'll return an object of boolean values * for every key indicating if that size is * supported. Additionally an extra key 'none' * is returned to signal if no width is supported. * The widths must be passed in descending order. */constmq=useMediaQuery({desktop: 1920,laptop: 1024,tablet: 768,smartphone: 414,})/* * The above 'useMediaQuery' hooks transform the * breakpoint widths to these conditions: * desktop: min-width == 1920px * laptop: min-width == 1024px && max-width == 1919px * tablet: min-width == 768px && max-width == 1023px * smartphone: min-width == 414px && max-width == 767px * none: max-width == 413px */return(<div>{desktop&&<p>I'm visible on desktops</p>}{laptop&&<p>I'm visible on laptops</p>}{tablet&&<p>I'm visible on tablets</p>}{smartphone&&<p>I'm visible on smartphones</p>}{none&&<p>This screen size is not managed :(</p>}<hr/>{mq.desktop&&<p>I'm visible on desktops too</p>}{mq.laptop&&<p>I'm visible on laptops too</p>}{mq.tablet&&<p>I'm visible on tablets too</p>}{mq.smartphone&&<p>I'm visible on smartphones too</p>}{mq.none&&<p>This screen size is not managed here too :(</p>}</div>)}

useRectRef

Useful to keep a reference to the bounding client rect of a DOM node.

How to use it in your React component:

importReactfrom'react'import{useRectRef}from'@rs1/react-hooks'exportdefaultprops=>{const[rect,sectionRef]=useRectRef()return(<divref={sectionRef}>{`I'm ${rect.width}px x ${rect.height}px, try resizing the window!`}</div>)}

useRefEffect

Useful in combination with useDynamicRef to react to a DOM node change.

How to use it in your React component:

importReact,{useReducer}from'react'import{useRefEffect,useDynamicRef}from'@rs1/react-hooks'exportdefaultprops=>{const[header,toggle]=useReducer(s=>!s,true)const[section,sectionRef]=useDynamicRef(null,false)useRefEffect(section,()=>{console.log(`The section tag is now ${section?.tagName}`)},[])return(<div><buttononClick={toggle}>Toggle</button><hr/>{header ? (<headerref={sectionRef}style={{width: '100%',minHeight: '200px',background: 'red',}}/>) : (<footerref={sectionRef}style={{width: '100%',minHeight: '200px',background: 'blue',}}/>)}</div>)}

useSliderRef

Useful to transform any DOM node in a horizontal slider, handling touch and drag events.

How to use it in your React component:

importReactfrom'react'import{useSliderRef}from'@rs1/react-hooks'exportdefaultprops=>{const[value,sliderRef]=useSliderRef(/* Initial ref value: */null,/* Initial slider value: */0,/* Slider direction: */'LTR')/* * The slider direction should be one of: * 'LTR', 'RTL', 'TTB' or 'BTT'. * 'LTR': horizontal - left to right (default) * 'RTL': horizontal - right to left * 'TTB': vertical - top to bottom * 'BTT': vertical - bottom to top */return(<div><p>{`Touch me or drag me to change my value! Actually I'm ${Math.round(value*100)}%`}</p><divref={sliderRef}style={{width: '100%',height: '10px',background: 'red',cursor: 'pointer',}}/><divstyle={{width: `${Math.round(value*100)}%`,height: '10px',background: 'blue',marginTop: '-10px',pointerEvents: 'none',}}/></div>)}

About

A collection of useful custom React hooks.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages