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

@upstatement/react-hooks

v1.0.2

Published

A collection of Upstatement's most-used React hooks

Downloads

6

Readme

@upstatement/react-hooks

A collection of Upstatement's most-used React hooks

A collection of Upstatement's most-used React hooks across projects, updated to have first-class TypeScript support!

Table of Contents

Requirements

This package has the following peer dependencies:

  • React v16.8.0+ (for hooks ⚓️)

Installation

With npm:

$ npm install @upstatement/react-hooks

With yarn:

$ yarn add @upstatement/react-hooks

Then with a module bundler like webpack, use as you would anything else:

// using ES6 modules
import { useMultiRef, useSet } from '@upstatement/react-hooks';
import useMultiRef from '@upstatement/react-hooks/dist/esm/useMultiRef';

// using CommonJS modules
const { useMultiRef, useSet } = require('@upstatement/react-hooks');
const useMultiRef = require('@upstatement/react-hooks/dist/cjs/useMultiRef');

👋 Meet the Hooks

useState

This basic hook provides an extra layer of security over React's existing useState hook. While it functions the exact same as the original, our hook will no longer accept updates to the state post-unmount.

API

The API remains unchanged from React's useState hook: https://reactjs.org/docs/hooks-reference.html#usestate

Usage

import { useState } from '@upstatement/react-hooks';

const App = () => {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count => count + 1);
  };

  return (
    <div>
      <h4>Count: {count}</h4>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

useStateReducer

This hook is a step between the useState and useReducer hooks, providing a way to create a mini state store inside your component.

API

const [state, set] = useStateReducer(initialState);

The initial state should be a record of key-value pairs. Similar to useState, these values can either be the exact value, or a function to be lazily evaluated when the hook is run. For example:

const [state, set] = useStateReducer({
  name: 'John',
  expensiveValue: () => {
    const initialState = someExpensiveComputation();
    return initialState;
  },
});

The set function contains a number of properties that update the respective values within the state. For example:

const [state, set] = useStateReducer({
  age: 6,
  maxAge: 8,
});

set.age(5); // Sets age to 5
set.age(age => age + 1); // Increases age by 1
set.age((age, state) => Math.min(age + 1, state.maxAge)); // Increases age by 1, capped by current state's maxAge value

Usage

import { useStateReducer } from '@upstatement/react-hooks';

const UserForm = ({ onSubmit }) => {
  const [state, set] = useStateReducer({
    name: '',
    age: 0,
    createdAt: () => new Date(),
  });

  return (
    <form onSubmit={onSubmit}>
      <input id="name" value={state.name} onChange={evt => set.name(evt.target.value)} />
      <input id="age" type="number" value={state.age} onChange={evt => set.age(evt.target.value)} />
    </form>
  );
};

usePrevious

This hook allows for tracking of the value of a given variable on a previous render.

API

const previousValue = usePrevious(currentValue);

The initial previous value returned will be the same as the current value.

It's important to note that the previous value does not update when the given value changes, but rather on every render.

Usage

import { usePrevious } from '@upstatement/react-hooks';

const Direction = ({ scrollY }) => {
  const previousScrollY = usePrevious(scrollY);

  if (scrollY === previousScrollY) {
    return null;
  } else if (scrollY > previousScrollY) {
    return <ArrowUp />;
  }
  return <ArrowDown />;
};

useMap

This hook allows for use of the ES6 Map as a state variable inside your React component.

API

const map = useMap(arrayOfTuples);
// Accepts the same initial value that Map's constructor does

All map methods can then be used as normal, including (but not limited to) map.set, map.has, and map.delete.

Usage

import { useMap, useState } from '@upstatement/react-hooks';

const DictionarySearch = () => {
  const dictionaryMap = useMap();

  const [search, setSearch] = useState('');
  const [term, setTerm] = useState('');
  const [definition, setDefinition] = useState('');

  const addDefinition = evt => {
    evt.preventDefault();
    dictionaryMap.add(term, definition);
    setTerm('');
    setDefinition('');
  };

  const onChange = setFunction => evt => {
    setFunction(evt.target.value);
  };

  return (
    <div>
      <input id="search" value={search} onChange={onChange(setSearch)} />
      {dictionaryMap.has(search) ? (
        <p style={{ color: 'green' }}>{dictionaryMap.get(search)}</p>
      ) : (
        <p style={{ color: 'red' }}>Term not found in dictionary.</p>
      )}
      <form onSubmit={addDefinition}>
        <input id="term" value={term} onChange={onChange(setTerm)} />
        <textarea id="definition" value={definition} onChange={onChange(setDefinition)}></textarea>
      </form>
    </div>
  );
};

useSet

Similar to useMap, this hook allows you to use an ES6 Set as a state variable inside your React component.

API

const set = useSet(arrayOfValues);
// Accepts the same initial value that Set's constructor does

All set methods can then be used as normal, including (but not limited to) set.add, set.has, and set.delete.

Usage

import { useSet } from '@upstatement/react-hooks';

const Shop = ({ items }) => {
  const cartSet = useSet();

  const addToCart = index => {
    const item = items[index];
    if (item) {
      cartSet.add(item.name);
    }
  };

  return (
    <div>
      <h2>Items</h2>
      <ul>
        {items.map(({ name, price }, index) => (
          <li key={name}>
            <p>{name}</p>
            <p>${price}</p>
            <button disabled={cartSet.has(name)} onClick={() => addToCart(index)}>
              Add to cart
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
};

useMultiRef

Allows for tracking multiple refs in the React DOM. This is particularly useful when looping over items.

API

const [refs, setRef] = useMultiRef();

Usage

import { useEffect } from 'react';
import { useMultiRef } from '@upstatement/react-hooks';
import { last } from 'lodash';

const Modal = ({ links }) => {
  const [linkRefs, setLinkRef] = useMultiRef();

  const lockModalFocus = evt => {
    if (evt.keyCode === 9) {
      // Pressed tab
      const linkEls = linkRefs.current;
      if (evt.shiftKey && document.activeElement === linkEls[0]) {
        evt.preventDefault();
        last(linkEls).focus();
      } else if (!evt.shiftKey && document.activeElement === last(linkEls)) {
        evt.preventDefault();
        linkEls[0].focus();
      }
    }
  };

  useEffect(() => {
    linkRefs.current[0].focus();
    window.addEventListener('keydown', lockModalFocus);
    return () => {
      window.removeEventListener('keydown', lockModalFocus);
    };
  }, []);

  return (
    <ul>
      {links.map(({ href, text }, index) => (
        <li key={index} ref={setLinkRef(index)}>
          <a href={href}>{text}</a>
        </li>
      ))}
    </ul>
  );
};

useForceUpdate

This utility hook provides a way to force the a component to update. It's recommended to only be used when the DOM is dependent on a ref value.

API

const update = useForceUpdate();

Every call to the update function will increase an internal tick. This in turn will force a re-render of the component.

Usage

This hook is actually used in our useSet and useMap hooks! A snippet of that code is found below:

import { useRef } from 'react';
import { useForceUpdate } from '@upstatement/react-hooks';

const useSet = iterable => {
  const update = useForceUpdate();
  const setRef = useRef(new Set(iterable));

  const set = new Set(setRef.current);

  set.add = value => {
    const newSet = setRef.add(value); // Add to our set reference
    update(); // force update to hook, recreating the `set` value
    return newSet;
  };

  return set;
};

Contributing

We welcome all contributions to our projects! Filing bugs, feature requests, code changes, docs changes, or anything else you'd like to contribute are all more than welcome! More information about contributing can be found in the contributing guidelines.

Code of Conduct

Upstatement strives to provide a welcoming, inclusive environment for all users. To hold ourselves accountable to that mission, we have a strictly-enforced code of conduct.

About Upstatement

Upstatement is a digital transformation studio headquartered in Boston, MA that imagines and builds exceptional digital experiences. Make sure to check out our services, work, and open positions!