Have ideas to improve npm?Join in the discussion! »

    use-callback-ref
    TypeScript icon, indicating that this package has built-in type declarations

    1.2.5 • Public • Published

    🤙 use-callback-ref 📞


    The same `useRef` but it will callback: 📞 Hello! Your ref was changed!
    Travis bundle size

    Keep in mind that useRef doesn't notify you when its content changes. Mutating the .current property doesn't cause a re-render. If you want to run some code when React attaches or detaches a ref to a DOM node, you may want to use a callback ref instead .... useCallbackRef instead.

    Hooks API Reference

    Read more about use-callback pattern and use cases:

    This library exposes helpers to handle any case related to ref lifecycle

    • useCallbackRef - react on hook change
    • mergeRefs - merge multiple refs together. For, actually, fork
    • transformRef - transform one ref to anther
    • refToCallback - convert RefObject to an old callback-style ref
    • assignRef - assign value to the ref, regardless of it's form

    All functions are tree shakable, but even together it's less then 300b.

    API

    💡 Some commands are hooks based, and returns the same refs/functions every render. But some are not, to be used in classes or non-react code.

    useRef API

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

    API is 99% compatible with React createRef and useRef, and just adds another argument - callback, which would be called on ref update.

    createCallbackRef - to replace React.createRef

    • createCallbackRef(callback) - would call provided callback when ref is changed.

    useCallbackRef - to replace React.useRef

    • useCallbackRef(initialValue, callback) - would call provided callback when ref is changed.

    callback in both cases is callback(newValue, oldValue). Callback would not be called if newValue and oldValue is the same.

    import {useRef, createRef, useState} from 'react';
    import {useCallbackRef, createCallbackRef} from 'use-callback-ref';
    
    const Component = () => {
      const [,forceUpdate] = useState();
      // I dont need callback when ref changes
      const ref = useRef(null); 
      
      // but sometimes - it could be what you need
      const anotherRef = useCallbackRef(null, () => forceUpdate());
      
      useEffect( () => {
        // now it's just possible
      }, [anotherRef.current]) // react to dom node change
    }

    💡 You can use useCallbackRef to convert RefObject into RefCallback, creating bridges between the old and the new code

    // some old component
    const onRefUpdate = (newValue) => {...}
    const refObject = useCallbackRef(null, onRefUpdate);
    // ...
    <SomeNewComponent ref={refObject}/>

    assignRef

    🤔 Use case: every time you need to assign ref manually, and you dont know the shape of the ref

    assignRef(ref, value) - assigns values to the ref. ref could be RefObject or RefCallback.

    🚫 ref.current = value // what if it's a callback-ref?
    🚫 ref(value) // but what if it's a object ref?
    
    import {assignRef} from "use-callback-ref";
    ✅ assignRef(ref, value); 
    

    useTransformRef (to replace React.useImperativeHandle)

    🤔 Use case: ref could be different. transformRef(ref, tranformer):Ref - return a new ref which would propagate all changes to the provided ref with applied transform

    // before
    const ResizableWithRef = forwardRef((props, ref) =>
      <Resizable {...props} ref={i => i && ref(i.resizable)}/>
    );
    
    // after
    
    const ResizableWithRef = forwardRef((props, ref) =>
      <Resizable {...props} ref={transformRef(ref, i => i ? i.resizable : null)}/>
    );

    refToCallback

    refToCallback(ref: RefObject): RefCallback - for compatibility between the old and the new code. For the compatibility between RefCallback and RefObject use useCallbackRef(undefined, callback)

    useMergeRefs

    mergeRefs(refs: arrayOfRefs, [defaultValue]):ReactMutableRef - merges a few refs together

    When developing low level UI components, it is common to have to use a local ref but also support an external one using React.forwardRef. Natively, React does not offer a way to set two refs inside the ref property. This is the goal of this small utility.

    import React from 'react'
    import {useMergeRefs} from 'use-callback-ref'
    
    const MergedComponent = React.forwardRef((props, ref) => {
      const localRef = React.useRef();
      // ...
      // both localRef and ref would be populated with the `ref` to a `div`
      return <div ref={useMergeRefs([localRef, ref])} />
    })

    💡 - useMergeRefs will always give you the same return, and you don't have to worry about [localRef, ref] unique every render.

    mergeRefs

    mergeRefs(refs: arrayOfRefs, [defaultValue]):ReactMutableRef - merges a few refs together is a non-hook based version. Will produce the new ref every run, causing the old one to unmount, and be populated with the null value.

    mergeRefs are based on https://github.com/smooth-code/react-merge-refs, just exposes a RefObject, instead of a callback

    mergeRefs are "safe" to use as a part of other hooks-based commands, but don't forget - it returns a new object every call.

    Similar packages:

    • apply-ref - applyRefs is simular to mergeRef, applyRef is similar to assignRef
    • useForkRef - useForkRef is simular to useMergeRefs, but accepts only two arguments.
    • react-merge-refs - merge-refs is simular to useMergeRefs, but not a hook and does not provide "stable" reference.

    Is it a rocket science? No, RefObject is no more than {current: ref}, and use-callback-ref is no more than getter and setter on that field.

    License

    MIT

    Install

    npm i use-callback-ref

    DownloadsWeekly Downloads

    1,029,358

    Version

    1.2.5

    License

    MIT

    Unpacked Size

    32.7 kB

    Total Files

    42

    Last publish

    Collaborators

    • avatar