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

react-common-state-hooks

v1.1.14

Published

A set of wrappers around React's useState hook for many common scenarios

Downloads

28

Readme

React Common State Hooks

Build Status Coverage Status

A set of wrappers around React's useState hook for many common scenarios. Written with TypeScript and equipped with typings, but available for use in any React project.

useToggle

For when you need to switch things back and forth from true to false. The first item in the return array is the current value, the second is a toggle function that always flips the value, the third value is a function that explicitly sets the value to true, and the last value is a function that explicitly sets the value to false.

const [ currentValue, toggle, setToTrue, setToFalse ] = useToggle(true);
// the same order of return values applies regardless of whether initially `true` or `false`
const [ currentValue, toggle, setToTrue, setToFalse ] = useToggle(false);

useToggleOnce

For when you need to flip the switch once, and never flip the value again for as long as the component is mounted. The first item in the return array is the current value, and the second item is the toggle function that will only change the value once.

const [ currentValue, toggleOnce ] = useToggleOnce(true);
console.log(currentValue); // true
toggleOnce();
console.log(currentValue); // false
toggleOnce();
console.log(currentValue); // false, now and FOREVER! (until component is unmounted)

useToggleValues

For when you need to flip between back and forth between two values that are not booleans. The first item in the return array is the current value, the second is a toggle function that always flips the value, the third value is a function that explicitly sets the value to the first value specified, and the last value is a function that explicitly sets the value to the second value specified.

const [ currentValue, toggle, setToA, setToB ] = useToggleValues('a', ['a', 'b']);
console.log(currentValue); // 'a'
toggle();
console.log(currentValue); // 'b'
setToA();
console.log(currentValue); // 'a'
setToB();
console.log(currentValue); // 'b'

useValues

For when you have an array of defined values and want functions that corresponding to changing the state for each one.

const [ currentValue, setToOne, setToTwo, setToThree, setToFour ] = useValues(1, [1, 2, 3, 4]);
console.log(currentValue); // 1
setToThree();
console.log(currentValue); // 3
setToTwo();
console.log(currentValue); // 2
setToFour();
console.log(currentValue); // 4

This becomes very useful when you have an array of elements mapped into individual components.

const values = [
  'User',
  'Admin',
  'Superadmin'
]
const initial = values[0];
const [ currentValue, ...listeners ] = useValues(initial, values);

return (
  <div>
    User is currently a {currentValue}
    {values.map((value, i) => (
      <button onClick={listeners[i]}>Change to {value}</button>
    ))}
  </div>
);

useRange

For when you have a range of numerical integer values and want functions to change state for each one. The range is specified as a two-item array after the initial specified value. The first item is the min value and the last value is the max. The range is exclusive for the max value.

const [ currentValue, setToOne, setToTwo, setToThree, setToFour ] = useRange(1, [1, 5]);
console.log(currentValue); // 1
setToThree();
console.log(currentValue); // 3
setToTwo();
console.log(currentValue); // 2
setToFour();
console.log(currentValue); // 4

// You can always use the spread operator to reduce the number of variables.
const [ currentValue, ...listeners ] = useRange(1, [1, 5]);

usePrevious

For when you want to keep track of a previous state value. By default, the first previous value is undefined. Since the only thing previous to the starting initial value is... nothingness. However, you can set the starting previous value to be the same as the initial value by passing in true for the second hook argument. The caveat here is that the previous value will be the same value twice in a row in the beginning.

Shout-out to Gabe Ragland for this one.

const [ current, toggle ] = useToggle(false);
const previous = usePrevious(current);
console.log(current); // false
console.log(previous); // undefined
toggle();
console.log(current); // true
console.log(previous); // false
toggle();
console.log(current); // false
console.log(previous); // true

// Setting the first previous value to be the same as the initial
const [ current, toggle ] = useToggle(false);
const previous = usePrevious(current, true);
console.log(current); // false
console.log(previous); // false
toggle();
console.log(current); // true
console.log(previous); // false (same as the one above)
toggle();
console.log(current); // false
console.log(previous); // true

useResolver

For when you want a function to be called and have its return value be used to set the state.

const [ currentValue, resolver ] = useResolver(null, () => {
  const value = runComplicatedOperation();
  const transformedValue = runAnotherOperation(value);
  return transformedValue; // this will be the new current value
});
resolver();

The second item in the returned array also accepts arguments and will pass those arguments to your resolver.

const [ currentValue, resolver ] = useResolver(null, (...args) => {
  console.log(args); // ['a', 'b']
  const value = runComplicatedOperation();
  const transformedValue = runAnotherOperation(value);
  return transformedValue; // this will be the new current value
});
resolver('a', 'b');

This hook may seem a little redundant since all it really does is reduce a single function call. But it can help clean up organization of logic when dealing with imported utility functions that you would like to separate from your React logic.

import React from 'react';
import { useResolver } from 'react-common-state-hooks';
import { utilityFn, runHeavyCalculations, doMoreLogic } from './utilities';

function Comp() {
  const [ currentValue, resolver ] = useResolver(null, utilityFn);
  return (
    <select onChange={(event) => {
      const selectValue = event.target.value;
      const calculated = runHeavyCalculations();
      const contextSpecific = doMoreLogic(calculated, selectValue);
      resolver(contextSpecific);
    }}>
      <option value="DAY">Day</option>
      <option value="WEEK">Week</option>
      <option value="YEAR">Year</option>
    </select>
  );
}

useAsyncResolver

For when you have an asynchronous operation and want the return value of a promise to be used to change your state.

The function passed in as the second hook argument MUST return a Promise. When the promise resolves successfully, the unwrapped value of the promise will be used to change the state and trigger a re-render.

const [ currentValue, resolver ] = useAsycnResolver(null, () => {
  return fetch('http://example.com/movies.json')
    .then(response => response.json()); // when this resolves, it will be the new value of the state
});
resolver();

// This is also valid
const [ currentValue, resolver ] = useAsycnResolver(null, async () => {
  const movies = await fetch('http://example.com/movies.json')
    .then(response => response.json());
  return movies;
});
resolver();

Just as with useResolver, arguments given to the second item in the returned array pass through to the resolver.

const [ currentValue, resolver ] = useAsycnResolver(null, async (...args) => {
  console.log(args); // ['a', 'b']
  const movies = await fetch('http://example.com/movies.json')
    .then(response => response.json());
  return movies;
});
resolver('a', 'b');

This function does not change the state or trigger a re-render if the returned Promise fails. For the time being, this library will not try to implement an API for that scenario. Given how every React app is different, async failure is a situation that is best left up to you to figure out.