# React Utils *other gists* [🔗 TypeScript type toolbelt](https://gist.github.com/ackvf/de21847e78083034252961d550963579) [🔗 TS/JS utility functions](https://gist.github.com/ackvf/68f992660a5eda645c4671d3599b2acf) --- - [useDependencies()](#file-hooks-usedependencies-ts) - Tool to analyze which hook dependencies trigger an update. Can also be used with ordinary arrays or objects to keep track or visualize changes. ```tsx const veryExpensiveHook = useMemo(() => expensive(), [error, loading, mintPrice, protocolFee, ...]) const analysis = useDependencyHook(() => expensive(), [error, loading, mintPrice, protocolFee, ...]) console.log(analysis) ```  - [useLessFormState()](#file-hooks-uselessformstate-ts) - Minimalistic, extensible, advanced & type-safe form-state management *library* with referentially stable handlers. with useless form ```tsx const [formState, { onInputChange }] = useLessFormState<MyFormType>({ name: '', address: '' }) return ( <> <input name='name' value={formState.name} onChange={onInputChange} /> <input name='address' value={formState.address} onChange={onInputChange} /> </> ) ``` without useless form ```tsx const [name, setName] = useState('') const [address, setAddress] = useState('') const handleNameChange = useCallback((event) => setName(event.target.value), [setName]) const handleAddressChange = useCallback((event) => setAddress(event.target.value), [setAddress]) return ( <> <input value={name} onChange={handleNameChange} /> <input value={address} onChange={handleAddressChange} /> </> ) ``` - [useLessFormErrors()](#file-hooks-uselessformerrors-ts) - Minimalistic, extensible, advanced & type-safe validation *library* with referentially stable handlers. It is compatible with `useLessFormState`. ```ts const formState = { name: 'qwerty', confirmName: 'yolo' } const formErrors = getFormErrors( formState, { name: [ // Manual rule definition consists of a validator function and a message. [v => v.length >= 5, 'Name is too short'], [v => v.includes('green'), 'Name is not green'], ], confirmName: [ // There are plenty of pre-made rules [check.minLength(5), 'Name is too short'], // and even full reusable validation objects! validations.required, // Access the full state too. [(value, state) => state.name === value, 'Names are not same.'], ], } ) ``` - [useQueue()](#file-hooks-usequeue-ts) - This state manager operates on a queue *(array)*, implementing custom actions `pop`, `push`, `shift`, `unshift`, that trigger re-renders. ```tsx const [queue, refQueue] = useQueue(['a', 'b', 'c']) queue.push('d') const first = queue.shift() function callback() { console.log(refQueue.current) } // always latest value ``` - [useCounter()](#file-hooks-usecounter-ts) - This is a simple counting state manager. Referentially stable. ```tsx const [step, next, prev, goTo, reset, refState] = useCounter() // initial state set to `0` const [counter, add, remove, , reset] = useCounter(2) // initial state set to `2` add() // +1 remove() // -1 reset() // =2 ``` - [useMultiwaySwitch()](#file-hooks-usemultiwayswitch-ts) - An extension to useCounter. This counting state manager toggles between `true` and `false` and counts the number of switches turned on. It is useful for asynchronous and concurrent actions as it can be controlled from multiple places and only turns off when every switch is turned off, e.g. when every action finishes, etc.., causing a state change, which triggers a re-render. - [useShallowState()](#file-hooks-useshallowstate-ts) - This state manager allows to store multiple keys similar to `this.setState()` from React Class Components. Any state updates are **shallowly merged** with the old state object, replacing any old properties and keeping those that did not change. ```tsx const [state, setState] = useShallowState({ a: 1, b: 1 }/* initial state */) setState((oldState) => ({ b: oldSate.b + 1 })) setState({ c: 3 }) // state is now { a: 1, b: 2, c: 3 } ``` - [useToggle()](#file-hooks-usetoggle-ts) - Primitive **boolean*** state manager built with `useReducer` with referentially stable convenience handlers. *(\*also supports `null`)* ```tsx const [state, toggle, , , , refState] = useToggle(/* true | false | null */) const submitForm = useCallback(() => { if (refState.current) {/* ... */} // always latest value }, [refState]) // never changes reference // ... later in the component return <button onClick={toggle}>{state ? 'ON' : 'OFF'}</button> ``` - [useForceUpdate()](#file-hooks-useforceupdate-ts) - This void state manager allows to trigger a re-render of a component. ```tsx const forceUpdate = useForceUpdate() // later forceUpdate() // or return <button onClick={forceUpdate}>Force update</button> ``` - [useOnFocusOutside()](#file-hooks-useonfocusoutside-ts) - This hook is used to detect mouse events and tab navigation outside of a given element. ```tsx useOnFocusOutside(/* id */'Dropdown', () => closeDropdown()) ``` - [getNodeText()](#file-getnodetext-md) [![react-getNodeText Sandbox screenshot][1]][1] - [ComponentWithGenerics](#file-componentwithgenerics-tsx) Type helper that allows to pass a generic type to a component and use it in the component's props. ```tsx interface MyForm { name: string, address: string } <Input<MyForm> name='name' /> // OK <Input<MyForm> name='yolo' /> // Error - 'yolo' is not assignable to 'name' | 'address' ``` - [🔗 Compose & Higher Order Components and Functions](https://gist.github.com/ackvf/0f2db59182d4c05b2c31757e55586bcb) - [🔗 React TypeScript sessions](https://gist.github.com/ackvf/72aee89e960d63ca417c2b1519fa46a7) - [🔗 React typings](https://gist.github.com/ackvf/21e976cf4970841482e2b14870549f63) [1]: https://i.sstatic.net/GO4NE.png