Skip to content

Instantly share code, notes, and snippets.

@SleeplessByte
Last active February 18, 2020 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save SleeplessByte/f509def1aeadec064c9f4f8335b5abf9 to your computer and use it in GitHub Desktop.
Save SleeplessByte/f509def1aeadec064c9f4f8335b5abf9 to your computer and use it in GitHub Desktop.
import { Dimensions, ScaledSize, InteractionManager } from "react-native";
import { useEffect, useState } from "react";
type EventValue = {
window: ScaledSize;
screen: ScaledSize;
};
/**
* Listens to dimension changes of "dim" and reports during an animation frame.
*
* When a dimension changes, schedules the update inside an animation frame.
* The other option is to schedule this instantly (useDimensionsSync) or
* to wait for an idle frame / until animations are done (useDimensionsIdle).
*
* @param dim screen or window, defaults to window
* @returns the ScaledSize of the dim
*/
export function useDimensions(dim: "screen" | "window" = "window"): ScaledSize {
const [dimensions, setDimensions] = useState(() => Dimensions.get(dim));
// Start listening to changes
useEffect(() => {
let request: number | undefined = undefined;
const updateDimensions = (nextDimensions: EventValue) => {
if (request) {
cancelAnimationFrame(request);
}
request = requestAnimationFrame(() => {
request = undefined;
setDimensions(nextDimensions[dim]);
});
};
Dimensions.addEventListener("change", updateDimensions);
return () => {
Dimensions.removeEventListener("change", updateDimensions);
request && cancelAnimationFrame(request);
};
}, [dim, setDimensions]);
return dimensions;
}
/**
* Listens to dimension changes of "dim".
*
* When a dimension changes, schedule this instantly. The other option is to
* schedules the update inside an animation frame (useDimensions) or to wait for
* an idle frame / until animations are done (useDimensionsIdle).
*
* @param dim screen or window, defaults to window
* @returns the ScaledSize of the dim
*/
export function useDimensionsSync(
dim: "screen" | "window" = "window"
): ScaledSize {
const [dimensions, setDimensions] = useState(() => Dimensions.get(dim));
// Start listening to changes
useEffect(() => {
let stillCareAboutTheCallback = true;
const updateDimensions = (nextDimensions: EventValue) => {
stillCareAboutTheCallback && setDimensions(nextDimensions[dim]);
};
Dimensions.addEventListener("change", updateDimensions);
return () => {
stillCareAboutTheCallback = false;
Dimensions.removeEventListener("change", updateDimensions);
};
}, [dim, setDimensions]);
return dimensions;
}
/**
* Listens to dimension changes of "dim" and reports when all other interactions
* are done runnning (e.g. animations).
*
* When a dimension changes, wait for an idle frame / until animations are done.
* The other option is to schedule the update inside an animation frame
* (useDimensions) or to schedule this instantly (useDimensionsSync).
*
* @param dim screen or window, defaults to window
* @returns the ScaledSize of the dim
*/
export function useDimensionsIdle(
dim: "screen" | "window" = "window"
): ScaledSize {
const [dimensions, setDimensions] = useState(() => Dimensions.get(dim));
// Start listening to changes
useEffect(() => {
let cancelable: { cancel(): void } | undefined = undefined;
const updateDimensions = (nextDimensions: EventValue) => {
if (cancelable) {
cancelable.cancel();
}
cancelable = InteractionManager.runAfterInteractions(() => {
setDimensions(nextDimensions[dim]);
});
};
Dimensions.addEventListener("change", updateDimensions);
return () => {
Dimensions.removeEventListener("change", updateDimensions);
cancelable && cancelable.cancel();
};
}, [dim, setDimensions]);
return dimensions;
}
/**
* Helper to get the window width. Reports the changed with on an animation
* frame.
*/
export function useWindowWidth(): number {
return useDimensions("window").width;
}
/**
* The MIT License
*
* Copyright 2020 Derk-Jan Karrenbeld
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment