File "use-merge-refs.js"
Full Path: /home/siazco/grocery.siazco.se/wp-content/plugins/better-wp-security/core/packages/hocs/src/use-merge-refs.js
File size: 2.51 KB
MIME-type: text/x-java
Charset: utf-8
/**
* WordPress dependencies
*/
import { useRef, useCallback, useLayoutEffect } from '@wordpress/element';
/**
* Merges refs into one ref callback. Ensures the merged ref callbacks are only
* called when it changes (as a result of a `useCallback` dependency update) or
* when the ref value changes. If you don't wish a ref callback to be called on
* every render, wrap it with `useCallback( ref, [] )`.
* Dependencies can be added, but when a dependency changes, the old ref
* callback will be called with `null` and the new ref callback will be called
* with the same node.
*
* @param {Array} refs The refs to be merged.
*
* @return {Function} The merged ref callback.
*/
export default function useMergeRefs( refs ) {
const element = useRef( null );
const didElementChange = useRef( false );
const previousRefs = useRef( refs );
const currentRefs = useRef( refs );
// Update on render before the ref callback is called, so the ref callback
// always has access to the current refs.
currentRefs.current = refs;
// If any of the refs change, call the previous ref with `null` and the new
// ref with the node, except when the element changes in the same cycle, in
// which case the ref callbacks will already have been called.
useLayoutEffect( () => {
refs.forEach( ( ref, index ) => {
const previousRef = previousRefs.current[ index ];
if (
typeof ref === 'function' &&
ref !== previousRef &&
didElementChange.current === false
) {
previousRef( null );
ref( element.current );
}
} );
previousRefs.current = refs;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, refs );
// No dependencies, must be reset after every render so ref callbacks are
// correctly called after a ref change.
useLayoutEffect( () => {
didElementChange.current = false;
} );
// There should be no dependencies so that `callback` is only called when
// the node changes.
return useCallback( ( value ) => {
// Update the element so it can be used when calling ref callbacks on a
// dependency change.
element.current = value;
didElementChange.current = true;
// When an element changes, the current ref callback should be called
// with the new element and the previous one with `null`.
const refsToUpdate = value ? currentRefs.current : previousRefs.current;
// Update the latest refs.
refsToUpdate.forEach( ( ref ) => {
if ( typeof ref === 'function' ) {
ref( value );
} else if ( ref && ref.hasOwnProperty( 'current' ) ) {
ref.current = value;
}
} );
}, [] );
}