Skip to content

React hooks that are re-used across different projects.

License

Notifications You must be signed in to change notification settings

AxisCommunications/react-hooks-shareable

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

react-hooks-shareable

React hooks

This repository provides an explicit list of useful React hooks so you can re-use them across different projects. The hooks that are provided in this repository are used by multiple projects

If you want to add a React hook or change an existing one, please create an issue or pull request.

Install

yarn add -D react react-hooks-shareable

Usage

useAnalytics

A hook to expose convenience methods for sending page views or events to Google Analytics.

Note: You will still need to set up Google Analytics in your project manually, IE adding the script tag and initialize it and make sure gtag is available on the window object. You also need to have @types/gtag.js as devDependency in your project

import { useEffect, useCallback } from 'react'
import { useAnalytics } from 'react-hooks-shareable'
import { Button } from 'someComponentLibrary'

const GoogleID = 'UA-00000000'

const MyComponent = () => {
  const { pageView, event } = useAnalytics(GoogleID)

  useEffect(() => {
    pageView({ page_path: '/myPage' })
  }, [pageView])

  const onClick = useCallback(() => {
    // A simple event
    event('Create', {
      event_category: 'EventCategory',
      event_label: 'Success',
      value: 10,
    })
    // An exception event
    event('exception', {
      description: 'Script error on line 32 in main.js',
      fatal: true, // set to true if the error is fatal
    })
  }, [event])

  return <Button label="Click me" onClick={onClick} />
}
useBoolean

A hook for easy handling of boolean values. It exposes up to four values and functions in the returned array.

const [currentValue, setTrue, setFalse, toggleValue] = useBoolean(initialValue)
import { useBoolean } from 'react-hooks-shareable'
import { ConfirmDialog } from 'someComponentLibrary'

const MyComponent = () => {
  const [isOpen, open, close, toggle] = useBoolean(false)

  return (
    <ConfirmDialog
      open={isOpen}
      onClose={close}
      title="Dialog"
      message="Are you sure?"
      confirmAction={{
        label: 'OK',
        onClick: close,
      }}
      cancelAction={{
        label: 'Cancel',
        onClick: close,
      }}
    />
  )
}
useClickOutside

A hook that fires a callback when a click (pointerdown) was registered outside of a component. Outside is defined as outside of your react tree, which means that this works with portals.

import { useDraggable } from 'react-hooks-shareable'

const MyComponent = () => {
  const handler = useClickOutside(e => {
    console.log('Clicked outside!')
  })

  return (
    <div onPointerDown={handler}>
      <span>Clicks here is inside</span>
      {ReactDOM.createPortal(
        <span>Clicks here are also inside</span>,
        portalContainer
      )}
    </div>
  )
}
useDeferredTrigger

A hook for debouncing a changing boolean value, with different delays depending on the direction of the trigger (determined by the base value).

Note: the trailing delay takes into account the time already spent in the "on" state of the trigger.

Mainly useful for loading states where one wants to guarantee a period without spinner (delay triggering the loading state), but then when it's loading, make sure the spinner is shown for a minimum amount of time (trailing delay of the trigger).

Default values:

delay - 100ms minDuration - 400ms

import { useDeferredTrigger } from 'react-hooks-shareable'

const MyComponent = () => {
  const initializing =
    gqlClient === undefined || credentials === undefined || online === undefined

  const waiting = useDeferredTrigger(initializing, {
    delay: 200,
    minDuration: 500,
  })

  if (waiting) {
    return <Spinner>
  }

  return <YourComponent />
}
useDraggable

A hook that provides a translation vector for an element that is being dragged.

import { useDraggable } from 'react-hooks-shareable'

const MyComponent = () => {
  const [[tx], onDragStart, dragging] = useDraggable(onDragEnd)

  return (
    <ResizeContainer left={tx}>
      <ResizeHandle onPointerDown={onDragStart} />
      <ResizeMarker dragging={dragging} />
    </ResizeContainer>
  )
}
useFocusDetection

A hook which detects if the browser and your page is in focus.

import { useFocusDetection } from 'react-hooks-shareable'

const MyComponent = () => {
  const hasFocus = useFocusDetection(1000)

  return <span>{`User ${hasFocus ? : 'is' : 'is not'} focusing on this page`}</span>
}
useHasOverflow

A hook for checking if an element has overflow.

import { useHasOverflow } from 'react-hooks-shareable'
import { SomeComponent } from 'someComponentLibrary'

const MyComponent = () => {
  const { hasOverflow, ref } = useHasOverflow()

  return <SomeComponent ref={ref} hasOverflow={hasOverflow} />
}
useId

A hook that returns a unique id.

import { useId } from 'react-hooks-shareable'

const MyComponent = () => {
  const id = useId('someId')

  return <YourComponent id={id} />
}
useInterval

A hook for delaying the execution.

import { useInterval } from 'react-hooks-shareable'

const MyComponent = () => {
  useInterval(() => console.log('Run'), 100)

  return <YourComponent />
}
useLocalStorage

A hook for accessing from or saving the values to localStorage.

import { useLocalStorage, getLocalStorage } from 'react-hooks-shareable'
import { Switch } from 'someComponentLibrary'

// Without hook
const storage = getLocalStorage()
const theme: ITheme | null = storage['theme']

// With hook
const MyComponent = () => {
  const [analytics, setAnalytics] = useLocalStorage<boolean | null>('analytics')

  return (
    <Switch
      label={t('label.shareData')}
      value={analytics === true}
      onChange={setAnalytics}
    />
  )
}
usePressed

A hook for easy detecting if the component is pressed.

import { usePressed } from 'react-hooks-shareable'

const MyComponent = () => {
  const ref = React.createRef<HTMLInputElement>()
  const pressed = usePressed(ref)

  useEffect(() => {
    if (pressed) {
      document.addEventListener('pointermove', posSetter)
      return () => document.removeEventListener('pointermove', posSetter)
    }
  }, [posSetter, pressed])

  return <YourComponent />
}
useResetScroll

A hook for easy resetting the scroll to top of ref.

import { useResetScroll } from 'react-hooks-shareable'

const MyComponent = () => {
  const tableContentRef = useRef<HTMLDivElement>(null)

  // Scroll to top when scrollKey changes
  useResetScroll(tableContentRef)

  return <TableContainer ref={tableRef} />
}
useScrollPosition

A hook for translating the scroll position for an element into atTop and atBottom boolean values, indicating if the scroll position is at the beginning or end of an element.

To signal that the onScroll function hasn't computed any position yet, atTop and atBottom can be undefined!

import { useScrollPosition } from 'react-hooks-shareable'

const MyComponent = () => {
  const { atTop, atBottom, scrollRef } = useScrollPosition()

  return (
    <ScrollContainer
      topHidden={atTop === false}
      bottomHidden={atBottom === false}
      ref={scrollRef}
    >
      {children}
    </ScrollContainer>
  )
}
useSelection

A hook to keep track of the selected items.

import { useSelection } from 'react-hooks-shareable'
import { Table, TableHeader, Typography, Menu } from 'someComponentLibrary'

const MyComponent = () => {
  const [selection, add, remove, reset] = useSelection()

  const onSelect = useCallback(
    (selected: boolean, id?: string) => {
      if (selected) {
        if (id !== undefined) {
          add(id)
        } else {
          reset(LONG_DEVICE_LIST.map(device => device.id))
        }
      } else {
        if (id !== undefined) {
          remove(id)
        } else {
          reset([])
        }
      }
    },
    [add, remove, reset]
  )

  return (
    <Table onSelect={onSelect} hasMenu={true}>
      <TableHeader
        selected={
          selection.size !== 0 && selection.size === LONG_DEVICE_LIST.length
        }
        partial={selection.size > 0 && selection.size < LONG_DEVICE_LIST.length}
        overlay={
          selection.size === 0 ? undefined : (
            <div>
              <Typography>Actions overlay</Typography>
            </div>
          )
        }
        menu={
          <Menu
            align="right"
            items={MENU_ITEMS.map(({ label, ...item }) => ({
              ...item,
              label,
              onClick: onClickHandler(label),
            }))}
          />
        }
      >
        {TABLE_HEADER_DATA.map(({ title }, id) => (
          <Typography key={id}>{title}</Typography>
        ))}
      </TableHeader>
    </Table>
  )
}
useSynchronizedAnimation

A hook for synchronizing web animations. The animations are synchronized to the document.timeline. This can for example be used to make spinners always be in sync with another, and over remounts.

.animation {
  animation: spin 4s linear infinite;
}

@keyframes spin {
  100% {
    transform: rotate(360deg);
  }
}
import { useSynchronizedAnimation } from 'react-hooks-shareable'

const MyAnimation = () => {
  const ref = useSynchronizedAnimation()

  return <div className="animation" ref={ref} />
}
useTrigger

A hook implementing a generic event.

The event can, for example, be used to trigger changes to effects.

The initial state of the event is undefined, otherwise nothing should be assumed of the event returns a triplet consisting of:

  1. an event
  2. a function to trigger the event
  3. a function to reset the event to its initial state
import { useCallback, useMemo } from 'react'
import { useTrigger } from 'react-hooks-shareable'

const MyComponent = () => {
  const [clearEvent, triggerClearEvent] = useTrigger()

  const tabs = useMemo(
    () => [
      {
        id: 'myId',
        label: 'myLabel',
      },
    ],
    []
  )

  const onTabSelected = useCallback(
    (tab: Tab) => {
      triggerClearEvent()
      setCurrentTab(tab)
    },
    [triggerClearEvent]
  )
  return (
    <YourComponent
      tabs={tabs}
      onTabSelected={onTabSelected}
      selectedTab={currentTab}
      clearEvent={clearEvent}
    />
  )
}
useUserActive

A hook for listening to activity on an element by the user.

import { useScrollPosition } from 'react-hooks-shareable'

const MyComponent = () => {
  const ref = React.createRef<HTMLInputElement>()
  const [userActivity, startUserActive, stopUserActive] = useUserActive(
    ref,
    4000
  )

  return <YourComponent />
}
useVisibleFocus

A hook for easy handling of component's focus.

import { useVisibleFocus } from 'react-hooks-shareable'

const MyComponent = () => {
  const { isPointerOn, isPointerOff, determineVisibleFocus, visibleFocus } =
    useVisibleFocus()

  return (
    <Button
      onPointerDown={isPointerOn}
      onPointerUp={isPointerOff}
      onFocus={determineVisibleFocus}
      visibleFocus={visibleFocus}
    >
      Content
    </Button>
  )
}