Skip to content

Commit

Permalink
Merge pull request #418 from wellyshen/v2
Browse files Browse the repository at this point in the history
Feat: v2 comes out!
  • Loading branch information
wellyshen authored Apr 3, 2021
2 parents 00d527b + 86b311b commit 945e9b4
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 127 deletions.
102 changes: 26 additions & 76 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ A React [hook](https://reactjs.org/docs/hooks-custom.html#using-a-custom-hook) t
- 🍰 Easy to handle [responsive components](#responsive-components), provides an alternative solution to the [container queries](https://wicg.github.io/container-queries) problem.
- 📦 Supports [border-box size measurement](#border-box-size-measurement).
- 🎛 Super flexible [API](#api) design to cover most cases for you.
- 🙈 Supports [conditional component](#conditional-component).
- 🔩 Supports custom `refs` for [some reasons](#use-your-own-ref).
- 📜 Supports [TypeScript](#working-in-typescript) type definition.
- 🗄️ Server-side rendering compatibility.
- 🦠 Tiny size ([~ 1.1kB gzipped](https://bundlephobia.com/result?p=react-cool-dimensions)). No external dependencies, aside for the `react`.
- 🦔 Tiny size ([~ 1kB gzipped](https://bundlephobia.com/result?p=react-cool-dimensions)). No external dependencies, aside for the `react`.

## Requirement

Expand Down Expand Up @@ -62,14 +60,17 @@ To report the size of an element by the `width` and `height` states.
import useDimensions from "react-cool-dimensions";

const App = () => {
const { ref, width, height, entry, unobserve, observe } = useDimensions({
onResize: ({ width, height, entry, unobserve, observe }) => {
// Triggered whenever the size of the target is changed
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={ref}>
<div ref={observe}>
Hi! My width is {width}px and height is {height}px
</div>
);
Expand All @@ -88,7 +89,7 @@ If you wish to update the state on the breakpoints changed, you can set the `upd
import useDimensions from "react-cool-dimensions";

const Card = () => {
const { ref, currentBreakpoint } = useDimensions({
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 },
Expand All @@ -101,7 +102,7 @@ const Card = () => {
});

return (
<div class={`card ${currentBreakpoint}`} ref={ref}>
<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>
Expand Down Expand Up @@ -136,7 +137,7 @@ import useDimensions from "react-cool-dimensions";
import { ResizeObserver } from "@juggle/resize-observer";

const App = () => {
const { ref, width, height } = useDimensions({
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
});
Expand All @@ -149,7 +150,7 @@ const App = () => {
padding: "10px",
border: "5px solid grey",
}}
ref={ref}
ref={observe}
>
{/* Now the width and height will be: 100px + 10px + 5px = 115px */}
Hi! My width is {width}px and height is {height}px
Expand All @@ -158,78 +159,37 @@ const App = () => {
};
```
## Conditional Component
There're two ways to use `react-cool-dimensions` with a conditional component.
Option 1, we can lazily start observing via the `observe` method:
```js
import { useState } from "react";
import useDimensions from "react-cool-dimensions";

const App = () => {
const [show, setShow] = useState(false);
const { observe, width, height } = useDimensions();

return (
<>
<button onClick={() => setShow(!show)}>Toggle</button>
{show && (
<div ref={observe}>
Hi! My width is {width}px and height is {height}px
</div>
)}
</>
);
};
```
## How to Share the `ref`?
Option 2, wrap the hook into the conditional component:
You can share the `ref` as follows:
```js
import { useState } from "react";
import { useRef } from "react";
import useDimensions from "react-cool-dimensions";

const MyComponent = () => {
const { ref, width, height } = useDimensions();

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

const App = () => {
const [show, setShow] = useState(false);
const ref = useRef();
const { observe } = useDimensions();

return (
<>
<button onClick={() => setShow(!show)}>Toggle</button>
{show && <MyComponent />}
</>
<div
ref={(el) => {
observe(el); // Set the target element for measuring
ref.current = el; // Share the element for other purposes
}}
/>
);
};
```
## Use Your Own `ref`
In case of you had a ref already or you want to share a ref for other purposes. You can pass in the ref instead of using the one provided by this hook.
```js
const ref = useRef();
const { width, height } = useDimensions({ ref });
```
## 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](#responsive-components) or implementing our own throttled/debounced function as below.
```js
import _ from "lodash";

const { ref, width, height } = useDimensions({
const returnObj = useDimensions({
onResize: _.throttle(() => {
// Triggered once per every 500 milliseconds
}, 500),
Expand All @@ -243,14 +203,6 @@ This hook supports [TypeScript](https://www.typescriptlang.org), you can tell th
```ts
import useInView from "react-cool-dimensions";

// Use `ref` method
const App = () => {
const { ref } = useDimensions<HTMLDivElement>();

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

// Use `observe` method
const App = () => {
const { observe } = useDimensions<HTMLDivElement | null>();

Expand All @@ -270,21 +222,19 @@ It's returned with the following properties.
| Key | Type | Default | Description |
| ------------------- | -------- | ------- | ---------------------------------------------------------------------------------------------------------------------- |
| `ref` | object | | Used to set the target element for measuring. |
| `observe` | function | | To set a target element for measuring or re-start observing the current target element. |
| `unobserve` | function | | To stop observing the current target element. |
| `width` | number | | The width of the target element in pixel. |
| `height` | number | | The height of the target element in pixel. |
| `currentBreakpoint` | string | | Indicates the current breakpoint of the [responsive components](#responsive-components). |
| `entry` | object | | The [ResizeObserverEntry](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserverEntry) of the target element. |
| `unobserve` | function | | To stop observing the target element. |
| `observe` | function | | To [lazily start](#conditional-component) or re-start observing the target element once it's stopped observing. |
### Parameter
The `options` provides the following configurations and event callback for you.
| Key | Type | Default | Description |
| -------------------------- | -------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ref` | object | | For [some reasons](#use-your-own-ref), you can pass in your own `ref` instead of using the built-in. |
| `breakpoints` | object | | Activates the responsive mode for [responsive components](#responsive-components) or [performance optimization](#performance-optimization). |
| `updateOnBreakpointChange` | boolean | `false` | Tells the hook to update the state on breakpoint changed. |
| `useBorderBoxSize` | boolean | `false` | Tells the hook to [measure the target element based on the border-box size](#border-box-size-measurement). |
Expand Down
12 changes: 8 additions & 4 deletions demo/App/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { FC, useState } from "react";
import { FC, useState, useRef } from "react";
import { Global, css } from "@emotion/react";
import normalize from "normalize.css";

Expand All @@ -20,13 +20,14 @@ const App: FC = () => {
h: 300,
});
const {
ref,
observe,
currentBreakpoint,
width,
height,
} = useDimensions<HTMLDivElement>({
} = useDimensions<HTMLDivElement | null>({
breakpoints: { XS: 0, SM: 100, MD: 200, LG: 300, XL: 400 },
});
const ref = useRef<HTMLDivElement | null>();

const resize = (x: number, y: number) => {
if (!ref.current) return;
Expand Down Expand Up @@ -83,7 +84,10 @@ const App: FC = () => {
<div
css={frame}
style={{ width: `${size.w}px`, height: `${size.h}px` }}
ref={ref}
ref={(el) => {
observe(el);
ref.current = el;
}}
>
<div css={bp}>{currentBreakpoint}</div>
<div>
Expand Down
Loading

0 comments on commit 945e9b4

Please sign in to comment.