react-use-ref-effect

an useEffect hook optimized for useRef

Usage no npm install needed!

<script type="module">
  import reactUseRefEffect from 'https://cdn.skypack.dev/react-use-ref-effect';
</script>

README

useRefEffect


An `useEffect` hook optimized for `useRef`.
Github Actions bundle size

Executes an effect directly after React attaches a ref to a DOM node.
Allows cleaning up once React detaches the DOM node from the ref again.

  • The hook does not triggering additional renderings.
  • The hook size is only 200b.

API

useRefEffect API

Use case: every time you have to react to ref change

  • const ref = useRefEffect(callback) - would call provided callback when ref is changed.

  • const ref = useRefEffect(callback, []) - would call provided callback when ref is changed or a dependency is changed - similar to useEffect.

  • const ref = useRefEffect(() => { return cleanupCallback }, []) - would call provided cleanUpcallback once the component unmounts or if react removes the referenced DOM element

import { useRefEffect } from 'react-use-ref-effect';

const Component = () => {

  const ref = useRefEffect((element) => {
    console.log('Element', element, 'is now available');
    return () => {
      console.log('Element', element, 'is no longer available');
    }
  }, []);

  return <div ref={ref}>Hello World</div>
}

Motivation

React is delivering two powerful hooks useRef and useEffect however they don't work properly in combination:

const ref = useRef();
useEffect(() => {
  // do sth with ref.current
}, [ref.current])

✅   doesn't trigger additional renderings on mount

🚫   fails to execute the effect for conditionally rendered components
(e.g. isOpen && <span ref={ref}>Demo</span>)

🚫   fails to execute the effect for lazy rendered components
(e.g. <LazyComponent><span ref={ref}>Demo</span></LazyComponent>)

🚫   fails to execute the effect if a child controls the time to mount
(e.g. <Slider waitFor={3000}><span ref={ref}>Demo</span></Slider>)



By using a pattern from the official react hooks faq useRefEffect can be used as a safe replacement:

const ref = useRefEffect((current) => {
  // do sth with current
}, [])

✅   doesn't trigger additional renderings on mount

✅   executes effect and effect cleanup for conditionally and lazy rendered components
(e.g. isOpen && <span ref={ref}>Demo</span>)

✅   executes effect and effect cleanup for lazy rendered components
(e.g. <LazyComponent><span ref={ref}>Demo</span></LazyComponent>)

✅   executes effect and effect cleanup if a child controls the time to mount
(e.g. <Slider waitFor={3000}><span ref={ref}>Demo</span></Slider>)

Similar packages:

License

MIT