Skip to content

Commit

Permalink
Fix useResizeObserver bugs (#65389)
Browse files Browse the repository at this point in the history
* Rename "_legacy" dir to "legacy"

* Fix circular dependency issue

* Fix bug that caused elements to not be unobserved.

* Add changelog

* Remove changelog entry

Co-authored-by: DaniGuardiola <daniguardiola@git.wordpress.org>
Co-authored-by: jsnajdr <jsnajdr@git.wordpress.org>
Co-authored-by: tyxla <tyxla@git.wordpress.org>
  • Loading branch information
4 people committed Sep 19, 2024
1 parent fe25bf1 commit a90e35b
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 43 deletions.
45 changes: 3 additions & 42 deletions packages/compose/src/hooks/use-resize-observer/index.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,14 @@
/**
* WordPress dependencies
*/
import { useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import useEvent from '../use-event';
import type { ObservedSize } from './_legacy';
import _useLegacyResizeObserver from './_legacy';
import { useResizeObserver as _useResizeObserver } from './use-resize-observer';
import type { ObservedSize } from './legacy';
import _useLegacyResizeObserver from './legacy';
/**
* External dependencies
*/
import type { ReactElement } from 'react';

// This is the current implementation of `useResizeObserver`.
//
// The legacy implementation is still supported for backwards compatibility.
// This is achieved by overloading the exported function with both signatures,
// and detecting which API is being used at runtime.
function _useResizeObserver< T extends HTMLElement >(
callback: ResizeObserverCallback,
resizeObserverOptions: ResizeObserverOptions = {}
): ( element?: T | null ) => void {
const callbackEvent = useEvent( callback );

const observedElementRef = useRef< T | null >();
const resizeObserverRef = useRef< ResizeObserver >();
return useEvent( ( element?: T | null ) => {
if ( element === observedElementRef.current ) {
return;
}
observedElementRef.current = element;

// Set up `ResizeObserver`.
resizeObserverRef.current ??= new ResizeObserver( callbackEvent );
const { current: resizeObserver } = resizeObserverRef;

// Unobserve previous element.
if ( observedElementRef.current ) {
resizeObserver.unobserve( observedElementRef.current );
}

// Observe new element.
if ( element ) {
resizeObserver.observe( element, resizeObserverOptions );
}
} );
}

/**
* Sets up a [`ResizeObserver`](https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API)
* for an HTML or SVG element.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { useCallback, useRef, useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import useResizeObserver from '../index';
import { useResizeObserver } from '../use-resize-observer';

export type ObservedSize = {
width: number | null;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* WordPress dependencies
*/
import { useRef } from '@wordpress/element';
/**
* Internal dependencies
*/
import useEvent from '../use-event';

// This is the current implementation of `useResizeObserver`.
//
// The legacy implementation is still supported for backwards compatibility.
// This is achieved by overloading the exported function with both signatures,
// and detecting which API is being used at runtime.
export function useResizeObserver< T extends HTMLElement >(
callback: ResizeObserverCallback,
resizeObserverOptions: ResizeObserverOptions = {}
): ( element?: T | null ) => void {
const callbackEvent = useEvent( callback );

const observedElementRef = useRef< T | null >();
const resizeObserverRef = useRef< ResizeObserver >();
return useEvent( ( element?: T | null ) => {
if ( element === observedElementRef.current ) {
return;
}

// Set up `ResizeObserver`.
resizeObserverRef.current ??= new ResizeObserver( callbackEvent );
const { current: resizeObserver } = resizeObserverRef;

// Unobserve previous element.
if ( observedElementRef.current ) {
resizeObserver.unobserve( observedElementRef.current );
}

// Observe new element.
observedElementRef.current = element;
if ( element ) {
resizeObserver.observe( element, resizeObserverOptions );
}
} );
}

0 comments on commit a90e35b

Please sign in to comment.