npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@haensl/react-hooks

v1.14.0

Published

Assorted React hooks.

Downloads

90

Readme

@haensl/react-hooks

Assorted React hooks.

NPM

npm version CircleCI

Installation

Via npm

$ npm install -S @haensl/react-hooks

Via yarn

$ yarn add @haensl/react-hooks

Usage

  1. Install @haensl/react-hooks

  2. Use hooks in your components:

import { useDebounce } from '@haensl/react-hooks';

const DebouncedButton = () => {
  const handler = useDebounce(() => {
    console.log('click');
  }, 50);

  return (
    <button
      onClick={ handler }
    >click me</button>
  );
};

Available hooks

useAnimationFrame(fn)

Uses requestAnimationFrame to animate a function fn. The callback is passed one single argument, the time delta in milliseconds that has passed between this and the last call. Please check the example below as well as the Codepen example.

Example
import React, { useState, useEffect } from 'react';
import { useAnimationFrame } from '@haensl/react-hooks';

const AnimatedTimer = () => {
  const [seconds, setSeconds] = useState(0);
  const [elapsed, setElapsed] = useState(0);

  useAnimationFrame((dt) => {
    setElapsed(elapsed + dt);
  });

  useEffect(() => {
    if (elapsed >= 1000) {
      setSeconds(seconds + 1);
      setElapsed(elapsed - 1000);
    }
  }, [elapsed]);

  return (
    <span>{ seconds }</span>
  );
};

→ Codepen example

useBoundingClientRect(ref, [debounceMs = 25])

Returns the DOM rectangle (initially null) as returned by getBoundingClientRect for the given container ref. Changes are debounced by 25 milliseconds by default. Customize the debounce interval via the optional debounceMs argument. Please check out the example below as well as the Codepen example.

Example

import React, { useRef } from 'react';
import { useBoundingClientRect } from '@haensl/react-hooks';

const RectTracker = () => {
  const ref = useRef();
  const containerRect = useBoundingClientRect(ref);

  if (!containerRect) {
    return (
      <div ref={ ref }>
        <span>no container rect</span>
      </div>
    );
  }

  return (
    <div ref={ ref }>
      <span>Container rect:</span>
      <span>Width: {containerRect.width}</span>
      <span>Height: {containerRect.height}</span>
    </div>
  );
};

→ Codepen example

useClassNames(states, [separator = ' '])

Compiles a states object into a CSS class name string. By default all keys in states are joined by a space (' ') but you can supply a custom separator to cater to the needs of your CSS module naming methodology of choice. Please check the examples below.

Example

import React, { useState } from 'react';
import { useClassNames } from '@haensl/react-hooks';

const MyComponent = () => {
  const [stateA, setStateA] = useState(false);
  const className = useClassNames({
    MyComponent: true, // always have MyComponent in class name
    MyComponent--stateA: stateA // add MyComponent--stateA when stateA is true
  });

  // className will be 'MyComponent' or 'MyComponent MyComponent--stateA'

  return (
    <div className={ className }>
      {
        // render content
      }
    </div>
  );
};

Example: custom separator

import React, { useState } from 'react';
import { useClassNames } from '@haensl/react-hooks';

const MyComponent = () => {
  const [stateA, setStateA] = useState(false);
  const className = useClassNames(
    {
      MyComponent: true, // always have MyComponent in class name
      stateA // add --stateA when stateA is true
    },
    '--'
  );

  // className will either be 'MyComponent' or 'MyComponent--stateA'

  return (
    <div className={ className }>
      {
        // render content
      }
    </div>
  );
};

useDebounce(fn, debounceMs)

Uses memoization to debounce fn by debounceMs milliseconds. Please check the example below as well as the Codepen example.

Example
import React from 'react';
import { useDebounce } from '@haensl/react-hooks';

const DebouncedButton = () => {
  const handler = useDebounce(() => {
    console.log('click');
  }, 50); // handler only fires when there were no calls for 50ms.

  return (
    <button
      onClick={ handler }
    >click me</button>
  );
};

→ Codepen example

useInterval(fn, intervalMs)

Calls a fn repeatedly every intervalMs milliseconds.

Example
import React, { useState, useCallback } from 'react';
import { useInterval } from '@haensl/react-hooks';

const MyAnimation = () => {
  const [frame, setFrame] = useState(0);

  // Update frame every 100 milliseconds
  useInterval(() => {
    setFrame((frame) => frame + 1);
  }, 100);

  return (
    <div>{ frame }</div>
  );
};

useIsMounted()

Returns a function to check whether or not the component invoking the hook is mounted.

Example
import React, { useEffect } from 'react';
import { useIsMounted } from '@haensl/react-hooks';
import api from 'somewhere';

const MyComponent = () => {
  const isMounted = useIsMounted();
  // load some data from the backend
  useEffect(() => {
    api.fetchData()
      .then((data) => {
        if (isMounted()) {
          // use data only if component is still mounted
        }
      });
  }, []);
}

useIsomorphicLayoutEffect(fn, deps)

This hooks resolves the common React warning when using useLayoutEffect in a serverside environment:

Warning: useLayoutEffect does nothing on the server, because its effect cannot be encoded into the server renderer’s output format. This will lead to a mismatch between the initial, non-hydrated UI and the intended UI. To avoid this, useLayoutEffect should only be used in components that render exclusively on the client. See https://fb.me/react-uselayouteffect-ssr for common fixes.

useIsomorphicLayoutEffect resolves to useLayoutEffect on the client and useEffect on the server. Use this hook instead of useLayoutEffect if your app uses serverside rendering (SSR).

Example
import React, { useRef } from 'react';
import { useIsomorphicLayoutEffect } from '@haensl/react-hooks';

const MyComponent = () => {
  const ref = useRef();

  // prevents serverside rendering warning
  useIsomorphicLayoutEffect(() => {
    if (ref.current) {
      // do stuff with ref
    }
  }, [ref]);

  return (
    <div ref={ ref }>
      // ...
    </div>
  )
}

useIsScrolling([el = window, scrollEndMs = 100])

Returns a boolean indicating whether or not the user is scrolling. You can subscribe to a specific element via the first argument, el (default: window). End of scrolling is determined by no incoming scroll events for scrollEndMs milliseconds (default: 100). Please check the example blow as well as the Codepen example

Example
import React from 'react';
import { useIsScrolling } from '@haensl/react-hooks';

const UserScrollTracker = () => {
  const isScrolling = useIsScrolling();

  return (
    <span>The user is currently { isScrolling ? '' : 'not' } scrolling</span>
  );
};

→ Codepen example

useLang({ defaultLang = 'en' }) => string

Returns the user's language setting from navigator.language. Use the defaultLang of the options parameter to set a default language. (default: 'en).

Example
import React from 'react';
import { useLang } from '@haensl/react-hooks';

const MyComponent = () => {
  const lang = useLang();

  return (
    <span>The user's preferred language is { lang }.</span>
  );
};

useOnScroll(fn, [el = window])

Subscribes to scroll events on the given element el (default: window). The callback function fn is passed the Event. Please check the example below as well as the Codepen example.

Example
import React, { useState } from 'react';
import { useOnScroll } from '@haensl/react-hooks';

const WindowScrollTracker = () => {
  const [windowScroll, setWindowScroll] = useState(0);

  useOnScroll(() => {
    setWindowScroll(window.scrollY);
  });

  return (
    <div className="WindowScrollTracker">
      <span>Window has scrolled down</span>
      <span>{ windowScroll }px</span>
    </div>
  );
};

→ Codepen example

usePrevious(value)

Keeps track of changes to a value, storing it's previous state.

Example
import { useEffect, useState } from 'react';
import { usePrevious, useWindowScroll } from '@haensl/react-hooks';

const ScrollDirectionTracker = () => {
  const scrollPosition = useWindowScroll();
  const previousScrollPosition = usePrevious(scrollPosition);
  const [scrollDirection, setScrollDirection] = useState('down');

  useEffect(() => {
    if (previousScrollPosition.y < scrollPosition.y) {
      setScrollDirection('down');
    } else if (previousScrollPosition.y > scrollPosition.y) {
      setScrollDirection('up');
    }
  }, [scrollPosition, previousScrollPosition]);

  return (
    <div className="ScrollDirectionTracker">
      <span>User is scrolling</span>
      <span>{ scrollDirection }px</span>
    </div>
  );
};

useTimeout(fn, timeoutMs = 0)

Calls fn once after intervalMs milliseconds.

Example
import React, { useState, useCallback } from 'react';
import { useClassNames, useTimeout } from '@haensl/react-hooks';

const MyComponent = () => {
  const [animate, setAnimate] = useState(false);

  // Start animation after 1s
  useTimeout(() => {
    setAnimate(true);
  }, 1000);

  const className = useClassNames({
    animate
  });

  return (
    <div
        className={ className }
    >
        // ...
    </div>
  );
};

useWindowScroll([debounceMs = 25])

Returns an object (null if there is no window) with properties x and y reflecting the the scroll position of the window or document. Scroll position updates are by default debounced by 25 milliseconds. This debounce interval can be customized via the optional debounceMs argument. Please check the example below as well as the Codepen example.

Example

import React, { useState } from 'react';
import { useWindowScroll } from '@haensl/react-hooks';

const windowScrollTracker = () => {
  const windowScroll = useWindowScroll();

  if (!windowScroll) {
    return (
      <div className="WindowScrollTracker">
        no scroll poistion
      </div>
    );
  }

  return (
    <div className="WindowScrollTracker">
      <span>Scroll x: {windowScroll.x}</span>
      <span>Scroll y: {windowScroll.y}</span>
    </div>
  );
};

→ Codepen example

useWindowSize([debounceMs = 25])

Returns an object (initially null) with properties width and height reflecting the innerWidth and innerHeight of the window object. Size updates are by default debounced by 25 milliseconds. This debounce interval can be customized via the optional debounceMs argument. Please check the example below as well as the Codepen example.

Example

import React, { useState } from 'react';
import { useWindowSize } from '@haensl/react-hooks';

const WindowSizeTracker = () => {
  const windowSize = useWindowSize();

  if (!windowSize) {
    return (
      <div className="WindowSizeTracker">
        <span>No window size</span>
      </div>
    );
  }

  return (
    <div className="WindowSizeTracker">
      <span>Window Size:</span>
      <span>width: { windowSize.width }px</span>
      <span>height: { windowSize.height }px</span>
    </div>
  );
};

→ Codepen example

Changelog

License