I did a lot of research trying to find a React Native component which could reference its own dimensions in order to scale different elements in its style, but could not find any solid examples. I created a hook which boils a component's dimension down to its simplest, easiest to use components and this is what I cooked up:
import React, { Dispatch, SetStateAction } from "react";
import { LayoutChangeEvent } from "react-native";
/**
* A function to be invoke when a component's layout changes; passed via the onLayout attribute.
*/
type OnLayoutFunc = (event: LayoutChangeEvent) => void;
/**
* The dimensions of a component.
*
*/
export class ComponentDimensions {
private dims: BasicDimensions;
private setDims: Dispatch<SetStateAction<BasicDimensions>>;
private onLayoutFunc: OnLayoutFunc;
/**
* Construct a {@link ComponentDimensions} object.
*/
constructor() {
const [dims, setDims] = React.useState<BasicDimensions>({ w: 0, h: 0 });
this.dims = dims;
this.setDims = setDims;
this.onLayoutFunc = (event: LayoutChangeEvent): void => {
const { width, height } = event.nativeEvent.layout;
this.setDims({ w: width, h: height });
};
}
/**
* The component's width.
*
* @return {number} width in pixels.
*/
public w(): number {
return this.dims.w;
}
/**
* The component's height.
*
* @return {number} height in pixels.
*/
public h(): number {
return this.dims.h;
}
/**
* The function to be passed to a {@link ReactElement ReactElement's} onLayout attribute.
*
* @return {OnLayoutFunc} function to be passed as an onLayout attribute.
*/
public getOnLayoutFunc(): OnLayoutFunc {
return this.onLayoutFunc;
}
}
/**
* React-Native hook to allow a component to reference its own dimensions.
*
* @return {ComponentDimensions} the dimensions of the component.
*/
export default function useDimensions(): ComponentDimensions {
return new ComponentDimensions();
}
/**
* The layout dimensions of the component.
*/
type BasicDimensions = {
/**
* The width of the component in pixels.
*/
w: number;
/**
* The height of the component in pixels.
*/
h: number;
};
This hook can be used like this:
import React from "react";
import { View } from "react-native";
import { ReactElement } from "react-native/node_modules/@types/react";
import useDimensions, { ComponentDimensions } from "../../hooks/useDimensions";
export default function HookExample(): ReactElement {
const dims: ComponentDimensions = useDimensions();
return (
<View
onLayout={dims.getOnLayoutFunc()}
style={{
width: "100%",
height: "100%"
}}
>
{/* A red circle. */}
<View
style={{
width: "20%",
height: dims.w(),
borderRadius: 150,
backgroundColor: "red",
}}
>
</View>
{/* A blue rectangle. */}
<View
style={{
width: "100%",
height: dims.w() / 4,
backgroundColor: "blue",
}}
>
</View>
</View>
);
}
I'm new to both TypeScript and React-Native, so I'd appreciate some feedback for how I can make this simpler or clean it up. Also, I don't have any intuition for performance in React, so I'd be interested in feedback about that if anyone has any.