🙋♂️ Made by @thekitze
Other projects:
- 💻 Sizzy - A browser for designers and developers, focused on responsive design
- 🏫 React Academy - Interactive React and GraphQL workshops
- 🔮 Glink - Changelogs, Roadmap, User Requests
- 🐶 Benji - Ultimate wellness and productivity platform
- 🤖 JSUI - A powerful UI toolkit for managing JavaScript apps
- 📹 YouTube Vlog - Follow my journey
Set of a helpful hooks, for different specific to some primitives types state changing helpers.
Contributors ✨
Thanks goes to these wonderful people (emoji key):
This project follows the all-contributors specification. Contributions of any kind welcome!
Has two APIs:
- First and original from v1 is based on object destructuring e.g.
const { value, toggle } = useBoolean(false)(Docs below) - Second API (recommended why?) is based on more idiomatic to React hooks API, e.g. like
useStatewith array destructuringconst [value, actions] = useBoolean(false)(Docs)
Install
yarn add react-hanger
Usage
import React, { Component } from 'react'; import { useInput, useBoolean, useNumber, useArray, useOnMount, useOnUnmount } from 'react-hanger'; const App = () => { const newTodo = useInput(''); const showCounter = useBoolean(true); const limitedNumber = useNumber(3, { lowerLimit: 0, upperLimit: 5 }); const counter = useNumber(0); const todos = useArray(['hi there', 'sup', 'world']); const rotatingNumber = useNumber(0, { lowerLimit: 0, upperLimit: 4, loop: true, }); return ( <div> <button onClick={showCounter.toggle}> toggle counter </button> <button onClick={() => counter.increase()}> increase </button> {showCounter.value && <span> {counter.value} </span>} <button onClick={() => counter.decrease()}> decrease </button> <button onClick={todos.clear}> clear todos </button> <input type="text" value={newTodo.value} onChange={newTodo.onChange} /> </div> ); };
Example
API reference (object destructuring)
How to import?
import { useBoolean } from 'react-hanger' // will import all of functions
import useBoolean from 'react-hanger/useBoolean' // will import only this function
useStateful
Just an alternative syntax to useState, because it doesn't need array destructuring.
It returns an object with value and a setValue method.
const username = useStateful('test'); username.setValue('tom'); console.log(username.value);
useBoolean
const showCounter = useBoolean(true);
Methods:
togglesetTruesetFalse
useNumber
const counter = useNumber(0); const limitedNumber = useNumber(3, { upperLimit: 5, lowerLimit: 3 }); const rotatingNumber = useNumber(0, { upperLimit: 5, lowerLimit: 0, loop: true, });
Methods:
Both increase and decrease take an optional amount argument which is 1 by default, and will override the step property if it's used in the options.
increase(amount = 1)decrease(amount = 1 )
Options:
lowerLimitupperLimitloopstep- sets the increase/decrease amount of the number upfront, but it can still be overriden bynumber.increase(3)ornumber.decrease(5)
useInput
const newTodo = useInput('');
<input value={newTodo.value} onChange={newTodo.onChange} />
<input {...newTodo.eventBind} /> <Slider {...newTodo.valueBind} />
Methods:
clearonChangeeventBind- binds thevalueandonChangeprops to an input that hase.target.valuevalueBind- binds thevalueandonChangeprops to an input that's using onlyvalueinonChange(like most external components)
Properties:
hasValue
useArray
const todos = useArray([]);
Methods:
push- similar to native doesn't return length thounshift- similar to native doesn't return length thopop- similar to native doesn't return element thoshift- similar to native doesn't return element thoclearremoveIndexremoveById- if array consists of objects with some specificidthat you pass all of them will be removedmodifyById- if array consists of objects with some specificidthat you pass these elements will be modified.move- moves item from position to position shifting other elements.
So if input is [1, 2, 3, 4, 5]
from | to | expected
3 | 0 | [4, 1, 2, 3, 5]
-1 | 0 | [5, 1, 2, 3, 4]
1 | -2 | [1, 3, 4, 2, 5]
-3 | -4 | [1, 3, 2, 4, 5]
useMap
const { value, set } = useMap([['key', 'value']]); const { value: anotherValue, remove } = useMap(new Map([['key', 'value']]));
Actions:
setdeleteclearinitialize- applies tuples or map instancessetValue
useSet
const set = useSet(new Set<number>([1, 2]));
useSetState
const { state, setState, resetState } = useSetState({ loading: false }); setState({ loading: true, data: [1, 2, 3] }); resetState();
Methods:
setState(value)- will merge thevaluewith the currentstate(like this.setState works in React)resetState()- will reset the currentstateto thevaluewhich you pass to theuseSetStatehook
Properties:
state- the current state
usePrevious
Use it to get the previous value of a prop or a state value. It's from the official React Docs. It might come out of the box in the future.
const Counter = () => { const [count, setCount] = useState(0); const prevCount = usePrevious(count); return ( <h1> Now: {count}, before: {prevCount} </h1> ); };
usePageLoad
const isPageLoaded = usePageLoad();
useScript
const { ready, error } = useScript({ src: 'https://example.com/script.js', startLoading: true, delay: 100, onReady: () => { console.log('Ready'); }, onError: (error) => { console.log('Error loading script ', error); }, });
useDocumentReady
const isDocumentReady = useDocumentReady();
useGoogleAnalytics
useGoogleAnalytics({ id: googleAnalyticsId, startLoading: true, delay: 500, });
useWindowSize
const { width, height } = useWindowSize();
useDelay
const done = useDelay(1000);
usePersist
const tokenValue = usePersist('auth-token', 'value');
useToggleBodyClass
useToggleBodyClass(true, 'dark-mode');
useOnClick
useOnClick((event) => { console.log('Click event fired: ', event); });
useOnClickOutside
// Pass ref to the element const containerRef = useOnClickOutside(() => { console.log('Clicked outside container'); });
useFocus
// pass ref to the element // call focusElement to focus the element const [elementRef, focusElement] = useFocus();
useImage
const { imageVisible, bindToImage } = useImage(src, onLoad, onError);
Migration from v1 to v2
- Migration to array based API is a bit more complex but recommended (especially if you're using ESLint rules for hooks). Take a look at this section in array API docs.
- All lifecycle helpers are removed. Please replace
useOnMount,useOnUnmountanduseLifecycleHookswithuseEffect. This:
useOnMount(() => console.log("I'm mounted!")); useOnUnmount(() => console.log("I'm unmounted")); // OR useLifecycleHooks({ onMount: () => console.log("I'm mounted!"), onUnmount: () => console.log("I'm unmounted!"), });
to:
useEffect(() => { console.log("I'm mounted!"); return () => console.log("I'm unmounted"); }, []);
bindandbindToInputare got renamed tovalueBindandeventBindrespectively onuseInputhook