hooks-for-react

A set of must use hooks necessary for daily work with react

Usage no npm install needed!

<script type="module">
  import hooksForReact from 'https://cdn.skypack.dev/hooks-for-react';
</script>

README

Hooks for React

A Set of Must use Hooks necessary for daily work with React

Table of contents

State

useSuperState


Use a state with super powers.

This hook is like a combination of useState, useMemo and useRef hooks at once.

Returns a stateful value, and a function to update it + a ref to the state value.

Definition

<S>(factory: S | ((prev: S) => S), deps?: DependencyList): [S, Dispatch<SetStateAction<S>>, MutableRefObject<S>]

Usage

You can use it as you normally do with the useState hook.

const [state, setState, stateRef] = useSuperState(/* Initial state */ 0)
const [state, setState, stateRef] = useSuperState(/* Initial state creator - run only once */ () => 0)

Or you can pass a factory function and a list of dependencies as you would do with the useMemo hook.

The state will be changed either by using setState or from outside when the list of dependencies changes.

Note: You have access to the previous state by the parameter passed to the factory function.

const [state, setState, stateRef] = useSuperState(
    // State factory - run if the dependency list changed
    prevState => (prevState || 0) + props.count,
    // Dependency list
    [props.count]
)

You can also change the state without triggering a new rendering, by changing the stateRef value..

stateRef.current = newValue

useBindState


Bind a state to an outside value.

When the outside value changes, the state will be updated with the new value.

Returns a stateful value and function to update it + ref to the state value.

Definition

<S>(value: S): [S, Dispatch<SetStateAction<S>>, MutableRefObject<S>]

usage

The outsideValue will create the initial state, and will also update the state when it changes.

const [state, setState, stateRef] = useBindState(outsideValue)

Callback

useSameCallback


This hook is just like the useCallback hook with an empty array. This means that the callback will not change during the life of the component.

Returns a reference to the initial passed callback.

Definition

<T extends (...args: any[]) => any>(callback: T): T

usage

const onClick = useSameCallback(() => console.log(exampleRef.current))

Ref

useSuperRef


Use a ref with super powers.

This hook is like a combination of useMemo and useRef hooks at once.

Returns a value, and a ref to the value.

Definition

<V>(factory: V | ((prev: V) => V), deps?: DependencyList): [V, MutableRefObject<V>]

Usage

You can use it as you normally do with the useRef hook.

const [value, valueRef] = useSuperRef()
const [value, valueRef] = useSuperRef(/* Initial value */ 0)

Or you can pass an initializer function.

const [value, valueRef] = useSuperRef(/* Initial value creator - only runs once */ () => 0)

Or you can pass a factory function and a list of dependencies as you would do with the useMemo hook.

The value will be changed either by using useRef.current or from outside when the list of dependencies changes.

Note: You have access to the previous value by the parameter passed to the factory function.

const [value, valueRef] = useSuperRef(
    // ref value factory - run if the dependency list changed
    prevValue => (prevValue || 0) + props.count,
    // Dependency list
    [props.count]
)

useBindRef


Bind a ref to an outside value.

When the outside value changes, the ref value will be updated to the new value.

Returns the ref object.

Definition

<V>(value: V): MutableRefObject<V>

usage

The outsideValue value will be the initial ref value and will also update the ref value when it changes.

const myRef = useBindRef(outsideValue)

useInnerRef


Convert forwardedRef to a new regular React ref object.

Useful when using forwardedRef and you want to use the ref as a regular ref within the component as well.

Returns the ref object.

Definition

<T>(ref: ForwardedRef<T>): MutableRefObject<T>

usage

const ExampleComp = forwardedRef((props, ref)=> {
    const innerRef = useInnerRef(ref)
    useEffect(
        ()=> console.log(innerRef.current),
        [innerRef.current]
    )
    return <div ref={innerRef}></div>
})

Lifecycles

useInitial


Use the initial value returned by the create function, which is invoked when the component initialized.

This hook is basically a substitute for the behavior of the constructor in the class components.

Returns the initial value.

Definition

<V>(create: () => V) => V

usage

const id = useInitial(() => Math.random())

useRun


This hook will run immediately if the dependency list changes.

The main difference between this hook and the React lifecycles hooks is: this hook is called immediately but the useEffect hook for example run after processing the component.

Returns an isFirstRun indicator.

Definition

(callback: () => void, deps: DependencyList): { isFirstRun: boolean, isFirstRunRef: MutableRefObject<boolean> }

usage

const ExampleComp = props => {
    const myRef = useRef(5)
    useRun(() => myRef.current += props.count, [props.count])
    return myRef.current > 10 && <div>Hello World!</div>
}

You also have additional data returns that can be useful in some cases.

const { isFirstRun, isFirstRunRef } = useRun(() => console.log(`Dependencies change`), [...someDeps])

useAsyncEffect


This hook is a modified version of React useEffect hook that adds a nice support for async callback effect.

You can achieve the same cleanup behavior as the native useEffect by accessing the effect argument and passing to it a callback. Note: You should call it above any async operation (AKA before the await keyword)

Note: If you don't pass an dependency list, the effect will rerun after every completed render.

Note: Use useLayoutAsyncEffect for the layout effect version.

Definition

(effect: (onCleanup: (execute: () => void | Promise<void>) => void) => Promise<void>, deps?: DependencyList): void

usage

useAsyncEffect(
    async () => {
        const user = await myApi.get('./user')
        setData(user)
    },
    []
)

With cleanup:

useAsyncEffect(
    async (onCleanup)=> {
        const ac = new AbortController()
        // Call onCleanup above any async operation
        onCleanup(
            // cleanup callback
            () => ac.abort()
        )
        const res = await fetch('./my-api', { signal: ac.signal })
        const data = await res.json()
        setData(data)
        // onCleanup(() => ac.abort()) -> This is NOT OK!
    },
    [someDep]
)

useIf


Run a effect callback when the first parameter is truthy.

Note: The Effect Callback can have a React useEffect Callback signature, or a useAsyncEffect Callback signature.

Note: Use useLayoutIf for the layout effect version.

Returns the truthiness of the condition passed in the first parameter.

Definition

(condition: unknown, callback: EffectCallback): boolean

usage

Except a React useEffect callback.

useIf(someValue === otherValue, () => {
    console.log(`It is equal`)
    // Cleanup
    return () => console.log(`Cleaned up`)
})

useAsyncEffect callback also will work.

useIf(someValue === otherValue, async onCleanup => {
    onCleanup(() => console.log(`Cleaned up`)) // Always put it above any async operation.
    const data = await api.send(`It is equal`)
    console.log(data)
})

And it will return the truthiness of the condition.

const conditionPass = useIf(someValue === otherValue, () => console.log(`It is equal`))

useMount


Run a callback when the component is mounted.

Note: The Effect Callback can have a React useEffect Callback signature, or a useAsyncEffect Callback signature.

Note: Use useLayoutMount for the layout effect version.

Definition

(callback: EffectCallback): void

usage

Except a React useEffect callback.

useMount(() => {
    console.log(`It is equal`)
    // Cleanup
    return () => console.log(`Cleaned up`)
})

Callback signature for useAsyncEffect should also will work.

useMount(async onCleanup => {
    onCleanup(() => console.log(`Cleaned up`)) // Always put it above any async operation.
    const data = await api.send(`It is equal`)
    console.log(data)
})

useIsMount


Get to know the component current mounted state.

Returns a boolean and a ref to the boolean.

Definition

(): [boolean, MutableRefObject<boolean>]

usage

const [isMount, isMountRef] = useIsMount()

useUnmount


Run a callback when the component is unmounted.

Returns the callback that get passed.

Definition

<C extends (()=> void | Promise<void>>)>(callback: C): C

usage

useUnmount(() => console.log(`Component unmounted`))
useUnmount(() => someSubscription.unsubscribe())

useRender


Give you a option to force the component to be render.

Returns a render function that can be invoked to render the component when you need so.

Definition

(): () => void

usage

const render = useRender()
useEffect(() => render(), [...someDeps]) // the component will render when the deps get changed.

Dom

useClassName


Join lists of dom element className to be one className string, and memoized it depending on dependency list.

Returns a string represents the combination of all className in the array list.

Definition

(factory: () => Array<string>, deps: DependencyList): string

usage

const myClassName = useClassName(
    // Define a factory that returns array of classNames
    () => [
        `flex black`,
        someCondition && `some-class other-class`,
        secondCondition ? `new-class-list`: ``
    ],
    // List of dependencies go here
    [someCondition, secondCondition]
)
<div className={myClassName}>Hello world</div>

useStyle


Create style and memoized it depending on dependency list.

Returns the created style object, ready for use as a property of html element.

Definition

(factory: () => CSSProperties, deps: DependencyList): CSSProperties

usage

const myStyle = useStyle(
    // Define a Factory that returns style object
    () => ({
        backgroundColor: someCondition && `black`,
        color: someCondition ? `white`: `black`
    }),
    // List of dependencies go here
    [someCondition]
)
<div style={myStyle}>Hello world</div>

useHover


Get a sense when a element dom get hovered.

Note: You can disabled the hook functionality by passing false to the enabled option.

Note: If you don't pass ref to the element by using the ref option, an ref will be created for you.

Returns a boolean represents the truthiness of the element hover state, and a ref to the element.

Definition

<T extends HTMLElement>({ ref, enabled }?: { ref?: MutableRefObject<T>, enabled?: boolean }): [boolean, MutableRefObject<T>]

usage

const [isHover, btnRef] = useHover()
<button ref={btnRef}>Hover Me</button>

You have also some options you can pass to the hook.

Here is an example of using pre created ref.

const btnRef = useRef()
const [isHover] = useHover({ ref: btnRef })

Also you can disabled the hover functionality and logic if you don`t need it right now.

Note: The default value for the enabled option is true.

const isMobile = true
const [isHover, btnRef] = useHover({ enabled: !isMobile })

Timer

useTimeout


Use a callback on amount of time after the dependency list changes.

Note: If you don't pass an dependency list, the effect will stop and rerun after every completed render.

Note: This hook used requestAnimationFrame behind the scenes, for performance reason.

Note: Use useLayoutTimeout for the layout effect version.

Returns a ref to the current result of requestAnimationFrame call.

Definition

(callback: () => void, ms?: number, deps?: DependencyList): MutableRefObject<number>

usage

const handleRef = useTimeout(
    /* callback */
    () => console.log(`DependencyList changes`),
    /* milliseconds */
    1000,
    /* Dependency List */
    [...someDeps]
)

And you can cancel the requestAnimationFrame like so.

cancelAnimationFrame(handleRef.current)

useInterval


Restart a interval on amount of time after the dependency list changes.

Note: If you don't pass an dependency list, the effect will rerun after every completed render.

Note: This hook used requestAnimationFrame behind the scenes, for performance reason.

Note: Use useLayoutInterval for the layout effect version.

Returns a ref to the current result of requestAnimationFrame call.

Definition

(callback: () => void, ms?: number, deps?: DependencyList): MutableRefObject<number>

usage

const handleRef = useInterval(
    /* callback */
    () => console.log(`DependencyList changes`),
    /* milliseconds */
    1000,
    /* DependencyList */
    [...someDeps]
)

And you can cancel the requestAnimationFrame like so.

cancelAnimationFrame(handleRef.current)

Logger

useLog


Log when parameters changed.

Returns a list holding the parameters that get passed.

Definition

<T>(...params: T): T

usage

useLog(props.count, props.className)
// Log to the console a list with the current value of the parameters

If you pass only one object parameter, it will compares the object deeply for tracking a changes and log the new object to the console.

useLog({ count: props.count, myState: state })
// Log the object when one of the properties changed.