Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat] add new Hook: useDevicePixelRatio with tests & stories #2531

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions docs/useDevicePixelRatio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# `useDefault`

React hook that returns the device pixel ratio and updates the value everytime the user zooms in/out.

## Usage

```jsx
import {useDevicePixelRatio} from 'react-use';

const Demo = () => {
const {ratio} = useDevicePixelratio();
return (
<p>{ratio}</p>
);
};
```
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"babel-plugin-dynamic-import-node": "2.3.3",
"eslint": "8.28.0",
"eslint-config-prettier": "8.5.0",
"eslint-config-react-app": "6.0.0",
"eslint-config-react-app": "7.0.1",
"eslint-plugin-flowtype": "8.0.3",
"eslint-plugin-import": "2.26.0",
"eslint-plugin-jsx-a11y": "6.6.1",
Expand Down
227 changes: 114 additions & 113 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,117 +1,118 @@
export { default as createMemo } from './factory/createMemo';
export { default as createReducerContext } from './factory/createReducerContext';
export { default as createReducer } from './factory/createReducer';
export { default as createStateContext } from './factory/createStateContext';
export { default as useAsync } from './useAsync';
export { default as useAsyncFn } from './useAsyncFn';
export { default as useAsyncRetry } from './useAsyncRetry';
export { default as useAudio } from './useAudio';
export { default as useBattery } from './useBattery';
export { default as useBeforeUnload } from './useBeforeUnload';
export { default as useBoolean } from './useBoolean';
export { default as useClickAway } from './useClickAway';
export { default as useCookie } from './useCookie';
export { default as useCopyToClipboard } from './useCopyToClipboard';
export { default as useCounter } from './useCounter';
export { default as useCss } from './useCss';
export { default as useCustomCompareEffect } from './useCustomCompareEffect';
export { default as useDebounce } from './useDebounce';
export { default as useDeepCompareEffect } from './useDeepCompareEffect';
export { default as useDefault } from './useDefault';
export { default as useDrop } from './useDrop';
export { default as useDropArea } from './useDropArea';
export { default as useEffectOnce } from './useEffectOnce';
export { default as useEnsuredForwardedRef, ensuredForwardRef } from './useEnsuredForwardedRef';
export { default as useEvent } from './useEvent';
export { default as useError } from './useError';
export { default as useFavicon } from './useFavicon';
export { default as useFullscreen } from './useFullscreen';
export { default as useGeolocation } from './useGeolocation';
export { default as useGetSet } from './useGetSet';
export { default as useGetSetState } from './useGetSetState';
export { default as useHarmonicIntervalFn } from './useHarmonicIntervalFn';
export { default as useHover } from './useHover';
export { default as useHoverDirty } from './useHoverDirty';
export { default as useIdle } from './useIdle';
export { default as useIntersection } from './useIntersection';
export { default as useInterval } from './useInterval';
export { default as useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect';
export { default as useKey } from './useKey';
export { default as createBreakpoint } from './factory/createBreakpoint';
export { default as createMemo } from "./factory/createMemo";
export { default as createReducerContext } from "./factory/createReducerContext";
export { default as createReducer } from "./factory/createReducer";
export { default as createStateContext } from "./factory/createStateContext";
export { default as useAsync } from "./useAsync";
export { default as useAsyncFn } from "./useAsyncFn";
export { default as useAsyncRetry } from "./useAsyncRetry";
export { default as useAudio } from "./useAudio";
export { default as useBattery } from "./useBattery";
export { default as useBeforeUnload } from "./useBeforeUnload";
export { default as useBoolean } from "./useBoolean";
export { default as useClickAway } from "./useClickAway";
export { default as useCookie } from "./useCookie";
export { default as useCopyToClipboard } from "./useCopyToClipboard";
export { default as useCounter } from "./useCounter";
export { default as useCss } from "./useCss";
export { default as useCustomCompareEffect } from "./useCustomCompareEffect";
export { default as useDebounce } from "./useDebounce";
export { default as useDeepCompareEffect } from "./useDeepCompareEffect";
export { default as useDefault } from "./useDefault";
export { default as useDrop } from "./useDrop";
export { default as useDropArea } from "./useDropArea";
export { default as useEffectOnce } from "./useEffectOnce";
export { default as useEnsuredForwardedRef, ensuredForwardRef } from "./useEnsuredForwardedRef";
export { default as useEvent } from "./useEvent";
export { default as useError } from "./useError";
export { default as useFavicon } from "./useFavicon";
export { default as useFullscreen } from "./useFullscreen";
export { default as useGeolocation } from "./useGeolocation";
export { default as useGetSet } from "./useGetSet";
export { default as useGetSetState } from "./useGetSetState";
export { default as useHarmonicIntervalFn } from "./useHarmonicIntervalFn";
export { default as useHover } from "./useHover";
export { default as useHoverDirty } from "./useHoverDirty";
export { default as useIdle } from "./useIdle";
export { default as useIntersection } from "./useIntersection";
export { default as useInterval } from "./useInterval";
export { default as useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
export { default as useKey } from "./useKey";
export { default as createBreakpoint } from "./factory/createBreakpoint";
// not exported because of peer dependency
// export { default as useKeyboardJs } from './useKeyboardJs';
export { default as useKeyPress } from './useKeyPress';
export { default as useKeyPressEvent } from './useKeyPressEvent';
export { default as useLatest } from './useLatest';
export { default as useLifecycles } from './useLifecycles';
export { default as useList } from './useList';
export { default as useLocalStorage } from './useLocalStorage';
export { default as useLocation } from './useLocation';
export { default as useLockBodyScroll } from './useLockBodyScroll';
export { default as useLogger } from './useLogger';
export { default as useLongPress } from './useLongPress';
export { default as useMap } from './useMap';
export { default as useMedia } from './useMedia';
export { default as useMediaDevices } from './useMediaDevices';
export { useMediatedState } from './useMediatedState';
export { default as useMethods } from './useMethods';
export { default as useMotion } from './useMotion';
export { default as useMount } from './useMount';
export { default as useMountedState } from './useMountedState';
export { default as useMouse } from './useMouse';
export { default as useMouseHovered } from './useMouseHovered';
export { default as useMouseWheel } from './useMouseWheel';
export { default as useNetworkState } from './useNetworkState';
export { default as useNumber } from './useNumber';
export { default as useObservable } from './useObservable';
export { default as useOrientation } from './useOrientation';
export { default as usePageLeave } from './usePageLeave';
export { default as usePermission } from './usePermission';
export { default as usePrevious } from './usePrevious';
export { default as usePreviousDistinct } from './usePreviousDistinct';
export { default as usePromise } from './usePromise';
export { default as useQueue } from './useQueue';
export { default as useRaf } from './useRaf';
export { default as useRafLoop } from './useRafLoop';
export { default as useRafState } from './useRafState';
export { default as useSearchParam } from './useSearchParam';
export { default as useScratch } from './useScratch';
export { default as useScroll } from './useScroll';
export { default as useScrolling } from './useScrolling';
export { default as useSessionStorage } from './useSessionStorage';
export { default as useSetState } from './useSetState';
export { default as useShallowCompareEffect } from './useShallowCompareEffect';
export { default as useSize } from './useSize';
export { default as useSlider } from './useSlider';
export { default as useSpeech } from './useSpeech';
export { default as useKeyPress } from "./useKeyPress";
export { default as useKeyPressEvent } from "./useKeyPressEvent";
export { default as useLatest } from "./useLatest";
export { default as useLifecycles } from "./useLifecycles";
export { default as useList } from "./useList";
export { default as useLocalStorage } from "./useLocalStorage";
export { default as useLocation } from "./useLocation";
export { default as useLockBodyScroll } from "./useLockBodyScroll";
export { default as useLogger } from "./useLogger";
export { default as useLongPress } from "./useLongPress";
export { default as useMap } from "./useMap";
export { default as useMedia } from "./useMedia";
export { default as useMediaDevices } from "./useMediaDevices";
export { useMediatedState } from "./useMediatedState";
export { default as useMethods } from "./useMethods";
export { default as useMotion } from "./useMotion";
export { default as useMount } from "./useMount";
export { default as useMountedState } from "./useMountedState";
export { default as useMouse } from "./useMouse";
export { default as useMouseHovered } from "./useMouseHovered";
export { default as useMouseWheel } from "./useMouseWheel";
export { default as useNetworkState } from "./useNetworkState";
export { default as useNumber } from "./useNumber";
export { default as useObservable } from "./useObservable";
export { default as useOrientation } from "./useOrientation";
export { default as usePageLeave } from "./usePageLeave";
export { default as usePermission } from "./usePermission";
export { default as usePrevious } from "./usePrevious";
export { default as usePreviousDistinct } from "./usePreviousDistinct";
export { default as usePromise } from "./usePromise";
export { default as useQueue } from "./useQueue";
export { default as useRaf } from "./useRaf";
export { default as useRafLoop } from "./useRafLoop";
export { default as useRafState } from "./useRafState";
export { default as useSearchParam } from "./useSearchParam";
export { default as useScratch } from "./useScratch";
export { default as useScroll } from "./useScroll";
export { default as useScrolling } from "./useScrolling";
export { default as useSessionStorage } from "./useSessionStorage";
export { default as useSetState } from "./useSetState";
export { default as useShallowCompareEffect } from "./useShallowCompareEffect";
export { default as useSize } from "./useSize";
export { default as useSlider } from "./useSlider";
export { default as useSpeech } from "./useSpeech";
// not exported because of peer dependency
// export { default as useSpring } from './useSpring';
export { default as useStartTyping } from './useStartTyping';
export { useStateWithHistory } from './useStateWithHistory';
export { default as useStateList } from './useStateList';
export { default as useThrottle } from './useThrottle';
export { default as useThrottleFn } from './useThrottleFn';
export { default as useTimeout } from './useTimeout';
export { default as useTimeoutFn } from './useTimeoutFn';
export { default as useTitle } from './useTitle';
export { default as useToggle } from './useToggle';
export { default as useTween } from './useTween';
export { default as useUnmount } from './useUnmount';
export { default as useUnmountPromise } from './useUnmountPromise';
export { default as useUpdate } from './useUpdate';
export { default as useUpdateEffect } from './useUpdateEffect';
export { default as useUpsert } from './useUpsert';
export { default as useVibrate } from './useVibrate';
export { default as useVideo } from './useVideo';
export { default as useStateValidator } from './useStateValidator';
export { useScrollbarWidth } from './useScrollbarWidth';
export { useMultiStateValidator } from './useMultiStateValidator';
export { default as useWindowScroll } from './useWindowScroll';
export { default as useWindowSize } from './useWindowSize';
export { default as useMeasure } from './useMeasure';
export { default as usePinchZoom } from './usePinchZoom';
export { useRendersCount } from './useRendersCount';
export { useFirstMountState } from './useFirstMountState';
export { default as useSet } from './useSet';
export { createGlobalState } from './factory/createGlobalState';
export { useHash } from './useHash';
export { default as useStartTyping } from "./useStartTyping";
export { useStateWithHistory } from "./useStateWithHistory";
export { default as useStateList } from "./useStateList";
export { default as useThrottle } from "./useThrottle";
export { default as useThrottleFn } from "./useThrottleFn";
export { default as useTimeout } from "./useTimeout";
export { default as useTimeoutFn } from "./useTimeoutFn";
export { default as useTitle } from "./useTitle";
export { default as useToggle } from "./useToggle";
export { default as useTween } from "./useTween";
export { default as useUnmount } from "./useUnmount";
export { default as useUnmountPromise } from "./useUnmountPromise";
export { default as useUpdate } from "./useUpdate";
export { default as useUpdateEffect } from "./useUpdateEffect";
export { default as useUpsert } from "./useUpsert";
export { default as useVibrate } from "./useVibrate";
export { default as useVideo } from "./useVideo";
export { default as useStateValidator } from "./useStateValidator";
export { useScrollbarWidth } from "./useScrollbarWidth";
export { useMultiStateValidator } from "./useMultiStateValidator";
export { default as useWindowScroll } from "./useWindowScroll";
export { default as useWindowSize } from "./useWindowSize";
export { default as useMeasure } from "./useMeasure";
export { default as usePinchZoom } from "./usePinchZoom";
export { useRendersCount } from "./useRendersCount";
export { useFirstMountState } from "./useFirstMountState";
export { default as useSet } from "./useSet";
export { createGlobalState } from "./factory/createGlobalState";
export { useHash } from "./useHash";
export { useDevicePixelRatio } from "./useDevicePixelRatio";
19 changes: 19 additions & 0 deletions src/useDevicePixelRatio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { useEffect, useState } from 'react';

export const useDevicePixelRatio = () => {
const [ratio, setRatio] = useState(1);

useEffect(() => {
const updatePixelRatio = () => {
setRatio(window.devicePixelRatio);
};
const mqString = `(resolution: ${window.devicePixelRatio}dppx)`;
const media = matchMedia(mqString);
media.addEventListener('change', updatePixelRatio);
return () => {
media.removeEventListener('change', updatePixelRatio);
};
}, [window.devicePixelRatio]);

return { ratio };
};
20 changes: 20 additions & 0 deletions stories/useDevicePixelRatio.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { storiesOf } from "@storybook/react";
import * as React from "react";
import { useDevicePixelRatio } from "../src";
import ShowDocs from "./util/ShowDocs";

const Demo = () => {
const { ratio } = useDevicePixelRatio();

return (
<main>
<article>
<button>{ratio}</button>
</article>
</main>
);
};

storiesOf("State/useDefault", module)
.add("Docs", () => <ShowDocs md={require("../docs/useDevicePixelRatio.md")} />)
.add("Demo", () => <Demo />);
38 changes: 38 additions & 0 deletions tests/useDevicePixelRatio.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { renderHook } from "@testing-library/react-hooks";
import { useDevicePixelRatio } from "../src";

beforeEach(() => {
Object.defineProperty(window, "devicePixelRatio", { value: 1, writable: true });
Object.defineProperty(window, "matchMedia", {
writable: true,
value: jest.fn().mockImplementation((query: MediaQueryList) => ({
matches: false,
media: query,
addEventListener: jest.fn(),
removeEventListener: jest.fn(),
})),
});
});

describe("testing initial value and update according to screen zoom", () => {
test("initial value should be window.devicePixelRatio", () => {
const { result } = renderHook(() => useDevicePixelRatio());

expect(result.current.ratio).toBe(window.devicePixelRatio);
});
test("testing ratio value after zooming in", async () => {
const { result, } = renderHook(() => useDevicePixelRatio());
Object.defineProperty(window, "devicePixelRatio", { value: 1.25, writable: true });
setTimeout(() => {
expect(result.current.ratio).toBe(window.devicePixelRatio);
}, 1000);
});
test("testing ratio value after zooming out1", async () => {
const { result, } = renderHook(() => useDevicePixelRatio());
Object.defineProperty(window, "devicePixelRatio", { value: 0.5, writable: true });
setTimeout(() => {
expect(result.current.ratio).toBe(window.devicePixelRatio);
}, 1000);

});
});