Skip to content

Commit

Permalink
feat: improve useWindowSize performance rAF
Browse files Browse the repository at this point in the history
  • Loading branch information
wardoost authored Sep 2, 2019
1 parent b96f097 commit 60a4937
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 9 deletions.
29 changes: 25 additions & 4 deletions src/__tests__/useWindowSize.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
import { act, renderHook } from '@testing-library/react-hooks';
import { replaceRaf } from 'raf-stub';
import useWindowSize from '../useWindowSize';

interface RequestAnimationFrame {
reset(): void;
step(): void;
}

declare var requestAnimationFrame: RequestAnimationFrame;

replaceRaf();

beforeEach(() => {
requestAnimationFrame.reset();
});

afterEach(() => {
requestAnimationFrame.reset();
});

// simulate window resize
function fireResize(type, value) {
switch (type) {
Expand All @@ -27,25 +45,28 @@ describe('useWindowSize', () => {
it('should update width', () => {
act(() => {
fireResize('width', 320);
hook.rerender();
requestAnimationFrame.step();
});

expect(hook.result.current.width).toBe(320);

act(() => {
fireResize('width', 640);
hook.rerender();
requestAnimationFrame.step();
});
expect(hook.result.current.width).toBe(640);
});

it('should update height', () => {
act(() => {
fireResize('height', 500);
hook.rerender();
requestAnimationFrame.step();
});
expect(hook.result.current.height).toBe(500);

act(() => {
fireResize('height', 1000);
hook.rerender();
requestAnimationFrame.step();
});
expect(hook.result.current.height).toBe(1000);
});
Expand Down
21 changes: 16 additions & 5 deletions src/useWindowSize.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { useEffect, useState } from 'react';
import { useRef, useEffect, useState } from 'react';
import { isClient } from './util';

const useWindowSize = (initialWidth = Infinity, initialHeight = Infinity) => {
const frame = useRef(0);
const [state, setState] = useState<{ width: number; height: number }>({
width: isClient ? window.innerWidth : initialWidth,
height: isClient ? window.innerHeight : initialHeight,
Expand All @@ -10,13 +11,23 @@ const useWindowSize = (initialWidth = Infinity, initialHeight = Infinity) => {
useEffect(() => {
if (isClient) {
const handler = () => {
setState({
width: window.innerWidth,
height: window.innerHeight,
cancelAnimationFrame(frame.current);

frame.current = requestAnimationFrame(() => {
setState({
width: window.innerWidth,
height: window.innerHeight,
});
});
};

window.addEventListener('resize', handler);
return () => window.removeEventListener('resize', handler);

return () => {
cancelAnimationFrame(frame.current);

window.removeEventListener('resize', handler);
};
} else {
return undefined;
}
Expand Down

0 comments on commit 60a4937

Please sign in to comment.