From 537fb1800ce2784388ec3d130a37bd26f6f2f62f Mon Sep 17 00:00:00 2001 From: Dani Guardiola Date: Mon, 9 Sep 2024 23:56:59 +0200 Subject: [PATCH] Add `useEvent` and `useObserveElementSize` to `@wordpress/compose` (#64943) * Simplify useResizeObserver * Loop through all resize entries * Add `useEvent` util. * Add `useObserveElementSize` util. * Simplify `useResizeObserver` by using `useEvent` and `useObserveElementSize`. * Switch to layout effect and accept refs too. * Prevent initial re-render in ResizeElement. * Better error message. * Improved example of useEvent. * Update packages/compose/src/hooks/use-event/index.ts Co-authored-by: Marin Atanasov <8436925+tyxla@users.noreply.github.com> * Sync docs. * Avoid redundant resize listener calls. * Switch to structural check. * Improve example. * Fix docs. * Make `useObserveElementSize` generic. * New API that returns a ref. * Make utility private for now. * Mark legacy `useResizeObserver` as such. * Rename `useObserveElementSize` to `useResizeObserver`. * Add return type. * Add signature as overload. * Add support for legacy API. * Move into subdirectory. * Minor import fix. * Fix docgen to support overloads (will pick up the first function signature). * Replace legacy utility with the new one. * Apply feedback. * Clean up and document. * Added changelog entries. --------- Co-authored-by: jsnajdr Co-authored-by: DaniGuardiola Co-authored-by: tyxla Co-authored-by: ciampo Co-authored-by: youknowriad --- packages/compose/CHANGELOG.md | 9 +- packages/compose/README.md | 52 ++++++-- packages/compose/src/hooks/use-event/index.ts | 51 ++++++++ .../{ => _legacy}/index.native.js | 0 .../{ => _legacy}/index.tsx | 44 +++---- .../{ => _legacy}/test/index.native.js | 2 +- .../src/hooks/use-resize-observer/index.ts | 119 ++++++++++++++++++ packages/compose/src/index.js | 1 + packages/docgen/lib/get-type-annotation.js | 4 + 9 files changed, 238 insertions(+), 44 deletions(-) create mode 100644 packages/compose/src/hooks/use-event/index.ts rename packages/compose/src/hooks/use-resize-observer/{ => _legacy}/index.native.js (100%) rename packages/compose/src/hooks/use-resize-observer/{ => _legacy}/index.tsx (86%) rename packages/compose/src/hooks/use-resize-observer/{ => _legacy}/test/index.native.js (96%) create mode 100644 packages/compose/src/hooks/use-resize-observer/index.ts diff --git a/packages/compose/CHANGELOG.md b/packages/compose/CHANGELOG.md index 2683fe8d79be7..cc0d7ef333f0d 100644 --- a/packages/compose/CHANGELOG.md +++ b/packages/compose/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased +### New Features + +- `useEvent`: a new utility that creates a stable callback function that has access to the latest state and can be used within event handlers and effect callbacks ([#64943](https://github.com/WordPress/gutenberg/pull/64943)). +- `useResizeObserver`: new and improved version of the utility (legacy API is still supported) ([#64943](https://github.com/WordPress/gutenberg/pull/64943)). + ## 7.7.0 (2024-09-05) ## 7.6.0 (2024-08-21) @@ -205,8 +210,8 @@ ### Breaking Changes -- Drop support for Internet Explorer 11 ([#31110](https://github.com/WordPress/gutenberg/pull/31110)). Learn more at https://make.wordpress.org/core/2021/04/22/ie-11-support-phase-out-plan/. -- Increase the minimum Node.js version to v12 matching Long Term Support releases ([#31270](https://github.com/WordPress/gutenberg/pull/31270)). Learn more at https://nodejs.org/en/about/releases/. +- Drop support for Internet Explorer 11 ([#31110](https://github.com/WordPress/gutenberg/pull/31110)). Learn more at . +- Increase the minimum Node.js version to v12 matching Long Term Support releases ([#31270](https://github.com/WordPress/gutenberg/pull/31270)). Learn more at . ## 3.25.0 (2021-03-17) diff --git a/packages/compose/README.md b/packages/compose/README.md index 0da853ad75c5a..b4e20a79bab0c 100644 --- a/packages/compose/README.md +++ b/packages/compose/README.md @@ -305,6 +305,29 @@ _Returns_ - `import('react').RefCallback`: Element Ref. +### useEvent + +Creates a stable callback function that has access to the latest state and can be used within event handlers and effect callbacks. Throws when used in the render phase. + +_Usage_ + +```tsx +function Component( props ) { + const onClick = useEvent( props.onClick ); + useEffect( () => { + onClick(); + // Won't trigger the effect again when props.onClick is updated. + }, [ onClick ] ); + // Won't re-render Button when props.onClick is updated (if `Button` is + // wrapped in `React.memo`). + return