README-ARRAY.md
April 22, 2021 ยท View on GitHub
API Reference (array destructuring)
How to import?
import { useBoolean } from 'react-hanger/array' // will import all of functions
import useBoolean from 'react-hanger/array/useBoolean' // will import only this function
useBoolean
const [showCounter, actions] = useBoolean(true);
Actions:
togglesetTruesetFalse
useNumber
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)
useInput
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-
useBindToInput
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)
useArray
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]
useMap
const [someMap, someMapActions] = useMap([["key", "value"]]);
const [anotherMap, anotherMapActions] = useMap(new Map([["key", "value"]]));
Actions:
setdeleteclearinitialize- applies tuples or map instancessetValue
useSet
const [ value, actions ] = useSet(new Set<number>([1, 2]))
value - a Set with only non mutating methods of a plain JS Set
Actions:
setValueaddremoveclear
useSetState
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
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>
);
};
Migration from object to array based
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.
useInput migration
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.