Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: streamich/react-use
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v12.4.0
Choose a base ref
...
head repository: streamich/react-use
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v12.5.0
Choose a head ref
  • 7 commits
  • 15 files changed
  • 5 contributors

Commits on Oct 12, 2019

  1. Copy the full SHA
    fb5a925 View commit details
  2. Copy the full SHA
    282f04b View commit details

Commits on Oct 13, 2019

  1. Copy the full SHA
    6afa6b4 View commit details
  2. Copy the full SHA
    2310f54 View commit details
  3. Unverified

    This commit is not signed, but one or more authors requires that any commit attributed to them is signed.
    Copy the full SHA
    a38f026 View commit details
  4. Copy the full SHA
    a624364 View commit details
  5. chore(release): 12.5.0 [skip ci]

    # [12.5.0](v12.4.0...v12.5.0) (2019-10-13)
    
    ### Features
    
    * useList allow pushing multiple items ([#621](#621)) ([a624364](a624364))
    semantic-release-bot committed Oct 13, 2019
    Copy the full SHA
    7955c3e View commit details
Showing with 156 additions and 56 deletions.
  1. +7 βˆ’0 CHANGELOG.md
  2. +2 βˆ’2 README.md
  3. +11 βˆ’12 docs/useInterval.md
  4. +9 βˆ’3 docs/useMeasure.md
  5. +5 βˆ’1 docs/useSize.md
  6. +3 βˆ’3 package.json
  7. +10 βˆ’10 src/__stories__/useInterval.story.tsx
  8. +3 βˆ’9 src/__stories__/useMeasure.story.tsx
  9. +3 βˆ’4 src/__stories__/useSize.story.tsx
  10. +39 βˆ’0 src/__tests__/useDeepCompareEffect.test.ts
  11. +13 βˆ’0 src/__tests__/useList.test.ts
  12. +13 βˆ’0 src/__tests__/useUpdateEffect.test.ts
  13. +4 βˆ’3 src/useInterval.ts
  14. +2 βˆ’2 src/useList.ts
  15. +32 βˆ’7 yarn.lock
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# [12.5.0](https://github.com/streamich/react-use/compare/v12.4.0...v12.5.0) (2019-10-13)


### Features

* useList allow pushing multiple items ([#621](https://github.com/streamich/react-use/issues/621)) ([a624364](https://github.com/streamich/react-use/commit/a624364))

# [12.4.0](https://github.com/streamich/react-use/compare/v12.3.2...v12.4.0) (2019-10-12)


4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -61,11 +61,11 @@
- [`usePageLeave`](./docs/usePageLeave.md) — triggers when mouse leaves page boundaries.
- [`useScroll`](./docs/useScroll.md) — tracks an HTML element's scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usescroll--docs)
- [`useScrolling`](./docs/useScrolling.md) — tracks whether HTML element is scrolling.
- [`useSize`](./docs/useSize.md) — tracks an HTML element's dimensions.
- [`useSize`](./docs/useSize.md) — tracks an HTML element's size.
- [`useStartTyping`](./docs/useStartTyping.md) — detects when user starts typing.
- [`useWindowScroll`](./docs/useWindowScroll.md) — tracks `Window` scroll position. [![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usewindowscroll--docs)
- [`useWindowSize`](./docs/useWindowSize.md) — tracks `Window` dimensions. [![][img-demo]](https://codesandbox.io/s/m7ln22668)
- [`useMeasure`](./docs/useMeasure.md) — tracks an HTML element's dimensions by [Resize Observer](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver/ResizeObserver).[![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemeasure--demo)
- [`useMeasure`](./docs/useMeasure.md) — tracks an HTML element's dimensions using the Resize Observer API.[![][img-demo]](https://streamich.github.io/react-use/?path=/story/sensors-usemeasure--demo)
<br/>
<br/>
- [**UI**](./docs/UI.md)
23 changes: 11 additions & 12 deletions docs/useInterval.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# `useInterval`

React hook that allow you using declarative `setInterval`.
A declarative interval hook based on [Dan Abramov's article on overreacted.io](https://overreacted.io/making-setinterval-declarative-with-react-hooks). The interval can be paused by setting the delay to `null`.

## Usage

@@ -11,32 +11,31 @@ import {useInterval} from 'react-use';
const Demo = () => {
const [count, setCount] = React.useState(0);
const [delay, setDelay] = React.useState(1000);
const [isRunning, toggleIsRunning] = useBoolean(true);

useInterval(() => {
setCount(count + 1);
}, delay);

function handleDelayChange(e) {
setDelay(Number(e.target.value));
}
useInterval(
() => {
setCount(count + 1);
},
isRunning ? delay : null
);

return (
<div>
<div>
delay: <input value={delay} onChange={handleDelayChange} />
delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
</div>
<h1>count: {count}</h1>
<div>
<button onClick={() => setDelay(delay ? null : 1000)}>{delay ? 'stop' : 'start'}</button>
<button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
</div>
</div>
);
};
```


## Reference

```js
useInterval(fn, delay?: number)
useInterval(callback, delay?: number)
```
12 changes: 9 additions & 3 deletions docs/useMeasure.md
Original file line number Diff line number Diff line change
@@ -1,24 +1,30 @@
# `useMeasure`

React sensor hook that reacts to changes in size of any of the observed elements.
React sensor hook that tracks dimensions of an HTML element using the [Resize Observer API](https://developer.mozilla.org/en-US/docs/Web/API/ResizeObserver).

## Usage

```jsx
import { useMeasure } from "react-use";

const Demo = () => {
const [ref, { width, height }] = useMeasure();
const [ref, { x, y, width, height, top, right, bottom, left }] = useMeasure();

return (
<div ref={ref}>
<div>x: {x}</div>
<div>y: {y}</div>
<div>width: {width}</div>
<div>height: {height}</div>
<div>top: {top}</div>
<div>right: {right}</div>
<div>bottom: {bottom}</div>
<div>left: {left}</div>
</div>
);
};
```

## Related hooks

- [useSize](./useSize.md)
- [useSize](./useSize.md)
6 changes: 5 additions & 1 deletion docs/useSize.md
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ import {useSize} from 'react-use';

const Demo = () => {
const [sized, {width, height}] = useSize(
({width}) => <div style={{border: '1px solid red'}}>Size me up! ({width}px)</div>,
({width}) => <div style={{background: 'red'}}>Size me up! ({width}px)</div>,
{ width: 100, height: 100 }
);

@@ -31,3 +31,7 @@ useSize(element, initialSize);

- `element` &mdash; sized element.
- `initialSize` &mdash; initial size containing a `width` and `height` key.

## Related hooks

- [useMeasure](./useMeasure.md)
6 changes: 3 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-use",
"version": "12.4.0",
"version": "12.5.0",
"description": "Collection of React Hooks",
"main": "lib/index.js",
"module": "esm/index.js",
@@ -69,7 +69,7 @@
"@semantic-release/changelog": "3.0.4",
"@semantic-release/git": "7.0.16",
"@semantic-release/npm": "5.1.13",
"@shopify/jest-dom-mocks": "^2.8.2",
"@shopify/jest-dom-mocks": "2.8.2",
"@storybook/addon-actions": "5.1.11",
"@storybook/addon-knobs": "5.1.11",
"@storybook/addon-notes": "5.1.11",
@@ -83,7 +83,7 @@
"babel-plugin-dynamic-import-node": "2.3.0",
"fork-ts-checker-webpack-plugin": "1.5.0",
"gh-pages": "2.1.1",
"husky": "3.0.8",
"husky": "3.0.9",
"jest": "24.9.0",
"keyboardjs": "2.5.1",
"lint-staged": "9.4.2",
20 changes: 10 additions & 10 deletions src/__stories__/useInterval.story.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import { storiesOf } from '@storybook/react';
import * as React from 'react';
import { useInterval } from '..';
import { useInterval, useBoolean } from '..';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
const [count, setCount] = React.useState(0);
const [delay, setDelay] = React.useState(1000);
const [isRunning, toggleIsRunning] = useBoolean(true);

useInterval(() => {
setCount(count + 1);
}, delay);

function handleDelayChange(e) {
setDelay(Number(e.target.value));
}
useInterval(
() => {
setCount(count + 1);
},
isRunning ? delay : null
);

return (
<div>
<div>
delay: <input value={delay} onChange={handleDelayChange} />
delay: <input value={delay} onChange={event => setDelay(Number(event.target.value))} />
</div>
<h1>count: {count}</h1>
<div>
<button onClick={() => setDelay(delay ? null : 1000)}>{delay ? 'stop' : 'start'}</button>
<button onClick={toggleIsRunning}>{isRunning ? 'stop' : 'start'}</button>
</div>
</div>
);
12 changes: 3 additions & 9 deletions src/__stories__/useMeasure.story.tsx
Original file line number Diff line number Diff line change
@@ -4,18 +4,12 @@ import { useMeasure } from '..';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
const [ref, { width, height }] = useMeasure();
const [ref, state] = useMeasure();

return (
<>
<div>width: {width}</div>
<div>height: {height}</div>
<div
style={{
background: 'red',
}}
ref={ref}
>
<pre>{JSON.stringify(state, null, 2)}</pre>
<div ref={ref} style={{ background: 'red' }}>
resize me
</div>
</>
7 changes: 3 additions & 4 deletions src/__stories__/useSize.story.tsx
Original file line number Diff line number Diff line change
@@ -4,15 +4,14 @@ import { useSize } from '..';
import ShowDocs from './util/ShowDocs';

const Demo = () => {
const [sized, { width, height }] = useSize(({ width: currentWidth }) => (
<div style={{ border: '1px solid red' }}>Size me up! ({currentWidth}px)</div>
const [sized, state] = useSize(({ width: currentWidth }) => (
<div style={{ background: 'red' }}>Size me up! ({currentWidth}px)</div>
));

return (
<div>
<pre>{JSON.stringify(state, null, 2)}</pre>
{sized}
<div>width: {width}</div>
<div>height: {height}</div>
</div>
);
};
39 changes: 39 additions & 0 deletions src/__tests__/useDeepCompareEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { renderHook } from '@testing-library/react-hooks';
import { useDeepCompareEffect } from '..';
import { useEffect } from 'react';

let options = { max: 10 };
const mockEffectNormal = jest.fn();
const mockEffectDeep = jest.fn();
const mockEffectCleanup = jest.fn();
const mockEffectCallback = jest.fn().mockReturnValue(mockEffectCleanup);

it('should run provided object once', () => {
const { rerender: rerenderNormal } = renderHook(() => useEffect(mockEffectNormal, [options]));
const { rerender: rerenderDeep } = renderHook(() => useDeepCompareEffect(mockEffectDeep, [options]));

expect(mockEffectNormal).toHaveBeenCalledTimes(1);
expect(mockEffectDeep).toHaveBeenCalledTimes(1);

options = { max: 10 };
rerenderDeep();
rerenderNormal();

expect(mockEffectNormal).toHaveBeenCalledTimes(2);
expect(mockEffectDeep).toHaveBeenCalledTimes(1);

options = { max: 10 };
rerenderNormal();
rerenderDeep();

expect(mockEffectNormal).toHaveBeenCalledTimes(3);
expect(mockEffectDeep).toHaveBeenCalledTimes(1);
});

it('should run clean-up provided on unmount', () => {
const { unmount } = renderHook(() => useDeepCompareEffect(mockEffectCallback, [options]));
expect(mockEffectCleanup).not.toHaveBeenCalled();

unmount();
expect(mockEffectCleanup).toHaveBeenCalledTimes(1);
});
13 changes: 13 additions & 0 deletions src/__tests__/useList.test.ts
Original file line number Diff line number Diff line change
@@ -104,6 +104,19 @@ it('should push duplicated element at the end of the list', () => {
expect(result.current[0]).not.toBe(initList); // checking immutability
});

it('should push multiple elements at the end of the list', () => {
const initList = [1, 2, 3];
const { result } = setUp(initList);
const [, utils] = result.current;

act(() => {
utils.push(4, 5, 6);
});

expect(result.current[0]).toEqual([1, 2, 3, 4, 5, 6]);
expect(result.current[0]).not.toBe(initList); // checking immutability
});

it('should filter current list by provided function', () => {
const initList = [1, -1, 2, -2, 3, -3];
const { result } = setUp(initList);
13 changes: 13 additions & 0 deletions src/__tests__/useUpdateEffect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { renderHook } from '@testing-library/react-hooks';
import { useUpdateEffect } from '..';

const mockEffectCleanup = jest.fn();
const mockEffectCallback = jest.fn().mockReturnValue(mockEffectCleanup);

it('should run effect on update', () => {
const { rerender } = renderHook(() => useUpdateEffect(mockEffectCallback));
expect(mockEffectCallback).not.toHaveBeenCalled();

rerender();
expect(mockEffectCallback).toHaveBeenCalledTimes(1);
});
7 changes: 4 additions & 3 deletions src/useInterval.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import { useEffect, useRef } from 'react';

const useInterval = (callback: Function, delay?: number | null) => {
const latestCallback = useRef<Function>(() => {});
const savedCallback = useRef<Function>(() => {});

useEffect(() => {
latestCallback.current = callback;
savedCallback.current = callback;
});

useEffect(() => {
if (delay !== null) {
const interval = setInterval(() => latestCallback.current(), delay || 0);
const interval = setInterval(() => savedCallback.current(), delay || 0);
return () => clearInterval(interval);
}

return undefined;
}, [delay]);
};
4 changes: 2 additions & 2 deletions src/useList.ts
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ export interface Actions<T> {
clear: () => void;
updateAt: (index: number, item: T) => void;
remove: (index: number) => void;
push: (item: T) => void;
push: (...items: T[]) => void;
filter: (fn: (value: T) => boolean) => void;
sort: (fn?: (a: T, b: T) => number) => void;
reset: () => void;
@@ -21,7 +21,7 @@ const useList = <T>(initialList: T[] = []): [T[], Actions<T>] => {
updateAt: (index, entry) =>
set(currentList => [...currentList.slice(0, index), entry, ...currentList.slice(index + 1)]),
remove: index => set(currentList => [...currentList.slice(0, index), ...currentList.slice(index + 1)]),
push: entry => set(currentList => [...currentList, entry]),
push: (...entry) => set(currentList => [...currentList, ...entry]),
filter: fn => set(currentList => currentList.filter(fn)),
sort: (fn?) => set(currentList => [...currentList].sort(fn)),
reset: () => set([...initialList]),
Loading