mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-22 22:44:52 +00:00
[add] useWindowDimensions hook
Add the 'useWindowDimensions' hook from React Native Close #1487
This commit is contained in:
committed by
Nicolas Gallagher
parent
4763cc71c6
commit
df1b62cd45
@@ -64,5 +64,6 @@ module.exports = {
|
||||
findNodeHandle: true,
|
||||
processColor: true,
|
||||
render: true,
|
||||
unmountComponentAtNode: true
|
||||
unmountComponentAtNode: true,
|
||||
useWindowDimensions: true
|
||||
};
|
||||
|
||||
@@ -7,12 +7,14 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import type { DisplayMetrics } from '../Dimensions';
|
||||
|
||||
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
import Dimensions from '../Dimensions';
|
||||
|
||||
const DeviceInfo = {
|
||||
Dimensions: {
|
||||
get windowPhysicalPixels() {
|
||||
get windowPhysicalPixels(): DisplayMetrics {
|
||||
const { width, height, fontScale, scale } = Dimensions.get('window');
|
||||
return {
|
||||
width: width * scale,
|
||||
@@ -21,7 +23,7 @@ const DeviceInfo = {
|
||||
fontScale
|
||||
};
|
||||
},
|
||||
get screenPhysicalPixels() {
|
||||
get screenPhysicalPixels(): DisplayMetrics {
|
||||
const { width, height, fontScale, scale } = Dimensions.get('screen');
|
||||
return {
|
||||
width: width * scale,
|
||||
|
||||
+30
-8
@@ -12,15 +12,31 @@ import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
import debounce from 'debounce';
|
||||
import invariant from 'fbjs/lib/invariant';
|
||||
|
||||
export type DisplayMetrics = {|
|
||||
fontScale: number,
|
||||
height: number,
|
||||
scale: number,
|
||||
width: number
|
||||
|};
|
||||
|
||||
type DimensionsValue = {|
|
||||
window?: DisplayMetrics,
|
||||
screen?: DisplayMetrics
|
||||
|};
|
||||
|
||||
type DimensionKey = 'window' | 'screen';
|
||||
|
||||
type DimensionEventListenerType = 'change';
|
||||
|
||||
const win = canUseDOM
|
||||
? window
|
||||
: {
|
||||
devicePixelRatio: undefined,
|
||||
innerHeight: undefined,
|
||||
innerWidth: undefined,
|
||||
innerHeight: (undefined: any),
|
||||
innerWidth: (undefined: any),
|
||||
screen: {
|
||||
height: undefined,
|
||||
width: undefined
|
||||
height: (undefined: any),
|
||||
width: (undefined: any)
|
||||
}
|
||||
};
|
||||
|
||||
@@ -28,12 +44,12 @@ const dimensions = {};
|
||||
const listeners = {};
|
||||
|
||||
export default class Dimensions {
|
||||
static get(dimension: string): Object {
|
||||
static get(dimension: DimensionKey): DisplayMetrics {
|
||||
invariant(dimensions[dimension], `No dimension set for key ${dimension}`);
|
||||
return dimensions[dimension];
|
||||
}
|
||||
|
||||
static set(initialDimensions: ?{ [key: string]: any }): void {
|
||||
static set(initialDimensions: ?DimensionsValue): void {
|
||||
if (initialDimensions) {
|
||||
if (canUseDOM) {
|
||||
invariant(false, 'Dimensions cannot be set in the browser');
|
||||
@@ -64,12 +80,18 @@ export default class Dimensions {
|
||||
}
|
||||
}
|
||||
|
||||
static addEventListener(type: string, handler: Function): void {
|
||||
static addEventListener(
|
||||
type: DimensionEventListenerType,
|
||||
handler: DimensionsValue => void
|
||||
): void {
|
||||
listeners[type] = listeners[type] || [];
|
||||
listeners[type].push(handler);
|
||||
}
|
||||
|
||||
static removeEventListener(type: string, handler: Function): void {
|
||||
static removeEventListener(
|
||||
type: DimensionEventListenerType,
|
||||
handler: DimensionsValue => void
|
||||
): void {
|
||||
if (Array.isArray(listeners[type])) {
|
||||
listeners[type] = listeners[type].filter(_handler => _handler !== handler);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @format
|
||||
* @flow strict-local
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import type { DisplayMetrics } from '../Dimensions';
|
||||
|
||||
import Dimensions from '../Dimensions';
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
export default function useWindowDimensions(): DisplayMetrics {
|
||||
const [dims, setDims] = useState(() => Dimensions.get('window'));
|
||||
useEffect(() => {
|
||||
function handleChange({ window }) {
|
||||
// $FlowFixMe
|
||||
setDims(window);
|
||||
}
|
||||
Dimensions.addEventListener('change', handleChange);
|
||||
// We might have missed an update between calling `get` in render and
|
||||
// `addEventListener` in this handler, so we set it here. If there was
|
||||
// no change, React will filter out this update as a no-op.
|
||||
setDims(Dimensions.get('window'));
|
||||
return () => {
|
||||
Dimensions.removeEventListener('change', handleChange);
|
||||
};
|
||||
}, []);
|
||||
return dims;
|
||||
}
|
||||
+6
-1
@@ -73,6 +73,9 @@ import TVEventHandler from './exports/TVEventHandler';
|
||||
// plugins
|
||||
import DeviceEventEmitter from './exports/DeviceEventEmitter';
|
||||
|
||||
// hooks
|
||||
import useWindowDimensions from './exports/useWindowDimensions';
|
||||
|
||||
export {
|
||||
// top-level API
|
||||
createElement as unstable_createElement,
|
||||
@@ -145,5 +148,7 @@ export {
|
||||
TimePickerAndroid,
|
||||
TVEventHandler,
|
||||
// plugins
|
||||
DeviceEventEmitter
|
||||
DeviceEventEmitter,
|
||||
// hooks
|
||||
useWindowDimensions
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user