import { useBoolean } from 'react-hanger/array' // will import all of functions
import useBoolean from 'react-hanger/array/useBoolean' // will import only this function
const [showCounter, actions] = useBoolean(true);Actions:
togglesetTruesetFalse
const [counter] = useNumber(0);
const [limitedNumber] = useNumber(3, { upperLimit: 5, lowerLimit: 3 });
const [rotatingNumber] = useNumber(0, {
upperLimit: 5,
lowerLimit: 0,
loop: true
});Actions:
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)
This one is unique, since it returns tuple as a first element, where first element is value and second is hasValue
Second element is actions as usual
type UseInputActions = {
setValue: React.Dispatch<SetStateAction<string>>;
onChange: (e: React.SyntheticEvent) => void
clear: () => void
}
type UseInput = [[string, boolean], UseInputActions]const [[newTodo], actions] = useInput("");<input value={newTodo} onChange={actions.onChange} />UseSetActions:
clearonChange- default native event.target.value handler
Properties:
hasValue-
Designed to be used in composition with useInput.
First and second elements are the same as `useInput.
Third are bindings to spread.
const [[newTodo], actions, { nativeBind, valueBind }] = useBindToInput(useInput(""));<input value={newTodo} onChange={actions.onChange} />
<input {...nativeBind} />
<Slider {...valueBind} />UseSetActions:
nativeBind- binds thevalueandonChangeprops to an input that hase.target.valuevalueBind- binds thevalueandonChangeprops to an input that's using onlyvalueinonChange(like most external components)
const [todos, actions] = useArray([]);UseSetActions:
pushunshiftpopshiftclearremoveIndexremoveById- 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]
const [someMap, someMapActions] = useMap([["key", "value"]]);
const [anotherMap, anotherMapActions] = useMap(new Map([["key", "value"]]));Actions:
setdeleteclearinitialize- applies tuples or map instancessetValue
const [ value, actions ] = useSet(new Set<number>([1, 2]))value - a Set with only non mutating methods of a plain JS Set
Actions:
setValueaddremoveclear
const [state, setState, resetState] = useSetState({ loading: false });
setState({ loading: true, data: [1, 2, 3] });Actions:
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
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>
);
};All value based hooks like useBoolean, useNumber etc. Are changed to
be using arrays, since it's more safe for reference equality, and also
makes it easier to use many useSmth without renaming value in destructuring.
So if you had
const { value: showHeader, ...showHeaderActions } = useBoolean(true)
const { value: showFooter, ...setShowFooterActions } = useBoolean(true)It will become
const [showHeader, showHeaderActions] = useBoolean(true)
const [showFooter, showFooterActions] = useBoolean(true)Note that despite this code seems to be looking the same, it's not. Cause showHeaderActions in v1 will result
in new object reference every rerender (because spreading creates new object, hence new reference). While in v2 actions are memoized
using useMemo and their reference will not change, cause they are not rely on value.
It enables us passing actions down the props without useless re-renders and excessive destructuring, it prevents useEffects and
other hooks from re-run/new reference creation if autofix of ESLint rule react-hooks/extraneous-deps will add them as dependencies automatically.
Also big change to the useInput
If before you was not using eventBind and nativeBind from them, then using the same approach from above
you will get what you want.
But if you need bindings you need to compose useInput with useBindToInput like that:
So if you had
const { value, eventBind, valueBind, onChange, hasValue } = useInput("")
<input value={value} onChange={onChange} />
<input {...eventBind} />
{hasValue && <Slider {...valueBind} />}It will become
const [[value, hasValue], actions, { eventBind, valueBind }] = useBindToInput(useInput(""))
<input value={value} onChange={actions.onChange} />
<input {...eventBind} />
{hasValue && <Slider {...valueBind} />}Note that first element in destructured array has tuple of [value, hasValue] since it's for values
and second argument is for actions e.g. only for functions.