Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

react-cool-dimensions

Package Overview
Dependencies
Maintainers
1
Versions
47
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

react-cool-dimensions

React hook to measure an element's size and handle responsive components.

  • 3.0.1
  • latest
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
72K
increased by11.84%
Maintainers
1
Weekly downloads
 
Created
Source

REACT COOL DIMENSIONS

A React hook that measure an element's size and handle responsive components with highly-performant way, using ResizeObserver. Try it you will 👍🏻 it!

❤️ it? ⭐️ it on GitHub or Tweet about it.

build status coverage status npm version npm downloads npm downloads gzip size All Contributors PRs welcome Twitter URL

demo

⚡️ Try yourself: https://react-cool-dimensions.netlify.app

Features

  • 🚀 Measures element's size with highly-performant way, using ResizeObserver.
  • 🎣 Easy to use, based on React hook.
  • 🍰 Easy to handle responsive components, provides an alternative solution to the container queries problem.
  • 📦 Supports border-box size measurement.
  • 🕹 Supports conditionally updating state.
  • 🎛 Super flexible API design to cover most cases for you.
  • 📜 Supports TypeScript type definition.
  • 🗄️ Server-side rendering compatibility.
  • 🦔 Tiny size (~ 1kB gzipped). No external dependencies, aside for the react.

Requirement

To use react-cool-dimensions, you must use react@16.8.0 or greater which includes hooks.

Installation

This package is distributed via npm.

$ yarn add react-cool-dimensions
# or
$ npm install --save react-cool-dimensions

Usage

react-cool-dimensions has a flexible API design, it can cover simple to complex use cases for you. Here are some examples to show you how does it work.

⚠️ Most modern browsers support ResizeObserver natively. You can also use polyfill for full browser support.

Basic Use Case

To report the size of an element by the width and height states.

import useDimensions from "react-cool-dimensions";

const App = () => {
  const { observe, unobserve, width, height, entry } = useDimensions({
    onResize: ({ observe, unobserve, width, height, entry }) => {
      // Triggered whenever the size of the target is changed...

      unobserve(); // To stop observing the current target element
      observe(); // To re-start observing the current target element
    },
  });

  return (
    <div ref={observe}>
      Hi! My width is {width}px and height is {height}px
    </div>
  );
};

💡 You don't have to call unobserve when the component is unmounted, this hook will handle it for you.

Responsive Components

We have media queries but those are based on the browser viewport not individual elements. In some cases, we'd like to style components based on the width of a containing element rather than the browser viewport. To meet this demand there's a proposal for container queries, but it still doesn't exist today...

No worries, react-cool-dimensions provides an alternative solution for us! We can activate the responsive mode by the breakpoints option. It's a width-based solution, once it's activated we can easily apply different styles to a component according to the currentBreakpoint state. The overall concept as below.

If you wish to update the state on the breakpoints changed, you can set the updateOnBreakpointChange option to true.

import useDimensions from "react-cool-dimensions";

const Card = () => {
  const { observe, currentBreakpoint } = useDimensions({
    // The "currentBreakpoint" will be the object key based on the target's width
    // for instance, 0px - 319px (currentBreakpoint = XS), 320px - 479px (currentBreakpoint = SM) and so on
    breakpoints: { XS: 0, SM: 320, MD: 480, LG: 640 },
    // Will only update the state on breakpoint changed, default is false
    updateOnBreakpointChange: true,
    onResize: ({ currentBreakpoint }) => {
      // Now the event callback will be triggered when breakpoint is changed
      // we can also access the "currentBreakpoint" here
    },
  });

  return (
    <div class={`card ${currentBreakpoint}`} ref={observe}>
      <div class="card-header">I'm 😎</div>
      <div class="card-body">I'm 👕</div>
      <div class="card-footer">I'm 👟</div>
    </div>
  );
};

Note: If the breakpoints option isn't set or there's no the defined breakpoint (object key) for a range of width. The currentBreakpoint will be empty string.

Conditionally Updating State

You can use the shouldUpdate option to conditionally update the state to reduce unnecessary re-renders as below.

const returnObj = useDimensions({
  shouldUpdate: ({ currentBreakpoint, width, height, entry }) => {
    // Will only update the state when the target element's width greater than 300px
    return state.width > 300;
  },
});

Note: When updateOnBreakpointChange and shouldUpdate are used at the same time, shouldUpdate has a higher priority.

Border-box Size Measurement

By default, the hook reports the width and height based on the content rectangle of the target element. We can include the padding and border for measuring by the useBorderBoxSize option. Please note, the width and height states are rely on the ResizeObserverEntry.borderBoxSize but it hasn't widely implemented by browsers therefore we need to use polyfill for this feature.

import useDimensions from "react-cool-dimensions";
import { ResizeObserver } from "@juggle/resize-observer";

const App = () => {
  const { observe, width, height } = useDimensions({
    useBorderBoxSize: true, // Tell the hook to measure based on the border-box size, default is false
    polyfill: ResizeObserver, // Use polyfill to make this feature works on more browsers
  });

  return (
    <div
      style={{
        width: "100px",
        height: "100px",
        padding: "10px",
        border: "5px solid grey",
      }}
      ref={observe}
    >
      {/* Now the width and height will be: 100px + 10px + 5px = 115px */}
      Hi! My width is {width}px and height is {height}px
    </div>
  );
};

How to Share A ref?

You can share a ref as follows:

import { useRef } from "react";
import useDimensions from "react-cool-dimensions";

const App = () => {
  const ref = useRef();
  const { observe } = useDimensions();

  return (
    <div
      ref={(el) => {
        observe(el); // Set the target element for measuring
        ref.current = el; // Share the element for other purposes
      }}
    />
  );
};

Performance Optimization

The onResize event will be triggered whenever the size of the target element is changed. We can reduce the frequency of the event callback by activating the responsive mode or implementing our own throttled/debounced function as below. Note that in order to throttle/debounce the function correctly, it will need to be memorized else it will be recreated on every render call.

import { useMemo } from "react";
import _ from "lodash";

const returnObj = useDimensions({
  onResize: useMemo(
    () =>
      _.throttle(() => {
        // Triggered once per every 500 milliseconds
      }, 500),
    []
  ),
});

Working in TypeScript

This hook supports TypeScript, you can tell the hook what type of element you are going to observe through the generic type:

const App = () => {
  const { observe } = useDimensions<HTMLDivElement>();

  return <div ref={observe} />;
};

💡 For more available types, please check it out.

API

const returnObj = useDimensions(options?: object);

Return object

It's returned with the following properties.

KeyTypeDefaultDescription
observefunctionTo set a target element for measuring or re-start observing the current target element.
unobservefunctionTo stop observing the current target element.
widthnumber or nullnullThe width of the target element in pixel. Null while target has not mounted.
heightnumber or nullnullThe height of the target element in pixel. Null while target has not mounted.Z
currentBreakpointstringIndicates the current breakpoint of the responsive components.
entryobjectThe ResizeObserverEntry of the target element.

Parameter

The options provides the following configurations and event callback for you.

KeyTypeDefaultDescription
breakpointsobjectActivates the responsive mode for responsive components or performance optimization.
updateOnBreakpointChangebooleanfalseTells the hook to update the state on breakpoint changed.
useBorderBoxSizebooleanfalseTells the hook to measure the target element based on the border-box size.
shouldUpdatefunctionTells the hook to conditionally update the state.
onResizefunctionIt's invoked whenever the size of the target element is changed. But in responsive mode, it's invoked based on the changing of the breakpoint rather than the size.
polyfillResizeObserverIt's used for injecting a polyfill.

ResizeObserver Polyfill

ResizeObserver has good support amongst browsers, but it's not universal. You'll need to use polyfill for browsers that don't support it. Polyfills is something you should do consciously at the application level. Therefore react-cool-dimensions doesn't include it.

We recommend using @juggle/resize-observer:

$ yarn add @juggle/resize-observer
# or
$ npm install --save @juggle/resize-observer

Then inject it by the polyfill option:

import { ResizeObserver } from "@juggle/resize-observer";

const { width, height } = useDimensions(ref, { polyfill: ResizeObserver });

Or pollute the window object:

import { ResizeObserver, ResizeObserverEntry } from "@juggle/resize-observer";

if (!("ResizeObserver" in window)) {
  window.ResizeObserver = ResizeObserver;
  // Only use it when you have this trouble: https://github.com/wellyshen/react-cool-dimensions/issues/45
  // window.ResizeObserverEntry = ResizeObserverEntry;
}

You could use dynamic imports to only load the file when the polyfill is required:

(async () => {
  if (!("ResizeObserver" in window)) {
    const module = await import("@juggle/resize-observer");
    window.ResizeObserver = module.ResizeObserver;
    // Only use it when you have this trouble: https://github.com/wellyshen/react-cool-dimensions/issues/45
    // window.ResizeObserverEntry = module.ResizeObserverEntry;
  }
})();

Articles / Blog Posts

💡 If you have written any blog post or article about react-cool-dimensions, please open a PR to add it here.

Contributors ✨

Thanks goes to these wonderful people (emoji key):

Welly
Welly

💻 📖 🚧
Runar Kristoffersen
Runar Kristoffersen

📖 💻 🤔
Ricardo Amaral
Ricardo Amaral

💻
Cornelius
Cornelius

🐛
Joseph Horton
Joseph Horton

📖
sirkrisp
sirkrisp

💻

This project follows the all-contributors specification. Contributions of any kind welcome!

Keywords

FAQs

Package last updated on 08 Mar 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc