Skip to content

Instantly share code, notes, and snippets.

@rkatic
Last active June 29, 2023 18:24
Show Gist options
  • Select an option

  • Save rkatic/943e0365ec1bc4a3a52e01beba3a3849 to your computer and use it in GitHub Desktop.

Select an option

Save rkatic/943e0365ec1bc4a3a52e01beba3a3849 to your computer and use it in GitHub Desktop.

Revisions

  1. rkatic revised this gist Jun 29, 2023. 1 changed file with 14 additions and 0 deletions.
    14 changes: 14 additions & 0 deletions memo-hooks.js
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,19 @@
    import { useEffect, useLayoutEffect, useRef, useState } from 'react'

    function shallowEqualArrays(a, b) {
    if (a.length !== b.length) {
    return false
    }

    for (let i = 0; i < a.length; ++i) {
    if (a[i] !== b[i]) {
    return false
    }
    }

    return true
    }

    /*
    A useMemo that ensures the result is not recalculated if provided dependencies did not change.
    https://react.dev/reference/react/useMemo#caveats
  2. rkatic revised this gist Jun 29, 2023. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion memo-hooks.js
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    import { useEffect, useRef, useState } from 'react'
    import { useEffect, useLayoutEffect, useRef, useState } from 'react'

    /*
    A useMemo that ensures the result is not recalculated if provided dependencies did not change.
  3. rkatic revised this gist Jun 29, 2023. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions memo-hooks.js
    Original file line number Diff line number Diff line change
    @@ -1,3 +1,5 @@
    import { useEffect, useRef, useState } from 'react'

    /*
    A useMemo that ensures the result is not recalculated if provided dependencies did not change.
    https://react.dev/reference/react/useMemo#caveats
  4. rkatic created this gist Jun 29, 2023.
    53 changes: 53 additions & 0 deletions memo-hooks.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,53 @@
    /*
    A useMemo that ensures the result is not recalculated if provided dependencies did not change.
    https://react.dev/reference/react/useMemo#caveats
    */
    export const useMemoStable = (fn, deps) => {
    const ref = useRef(null)

    if (!ref.current || !deps || !shallowEqualArrays(ref.current.deps, deps)) {
    ref.current = {
    value: fn(),
    deps: deps || [],
    }
    }

    return ref.current.value
    }

    const defaultEnhance = ({ status, value, reason }) => ({
    status,
    value,
    reason,
    loading: status === 'pending',
    ok: status === 'fulfilled',
    data: value,
    error: reason,
    })

    export const useAsyncMemo = (asyncFn, deps, enhance = defaultEnhance) => {
    const curr = useMemoStable(() => ({
    state: enhance({ status: 'pending' }),
    }), deps)

    const [, setDummyState] = useState()

    useLayoutEffect(() => {
    curr.aborter = new AbortController()
    return () => curr.aborter.abort()
    }, [curr])

    useEffect(() => {
    const { signal } = curr.aborter

    Promise.allSettled([asyncFn({ signal })])
    .then(([settled]) => {
    if (!signal.aborted) {
    curr.state = enhance(settled)
    setDummyState([])
    }
    })
    }, [curr])

    return curr.state
    }