Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Build performant React Native and Expo apps with best practices for lists, animations, and navigation
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
rules/ui-measure-views.md
1---2title: Measuring View Dimensions3impact: MEDIUM4impactDescription: synchronous measurement, avoid unnecessary re-renders5tags: layout, measurement, onLayout, useLayoutEffect6---78## Measuring View Dimensions910Use both `useLayoutEffect` (synchronous) and `onLayout` (for updates). The sync11measurement gives you the initial size immediately; `onLayout` keeps it current12when the view changes. For non-primitive states, use a dispatch updater to13compare values and avoid unnecessary re-renders.1415**Height only:**1617```tsx18import { useLayoutEffect, useRef, useState } from 'react'19import { View, LayoutChangeEvent } from 'react-native'2021function MeasuredBox({ children }: { children: React.ReactNode }) {22const ref = useRef<View>(null)23const [height, setHeight] = useState<number | undefined>(undefined)2425useLayoutEffect(() => {26// Sync measurement on mount (RN 0.82+)27const rect = ref.current?.getBoundingClientRect()28if (rect) setHeight(rect.height)29// Pre-0.82: ref.current?.measure((x, y, w, h) => setHeight(h))30}, [])3132const onLayout = (e: LayoutChangeEvent) => {33setHeight(e.nativeEvent.layout.height)34}3536return (37<View ref={ref} onLayout={onLayout}>38{children}39</View>40)41}42```4344**Both dimensions:**4546```tsx47import { useLayoutEffect, useRef, useState } from 'react'48import { View, LayoutChangeEvent } from 'react-native'4950type Size = { width: number; height: number }5152function MeasuredBox({ children }: { children: React.ReactNode }) {53const ref = useRef<View>(null)54const [size, setSize] = useState<Size | undefined>(undefined)5556useLayoutEffect(() => {57const rect = ref.current?.getBoundingClientRect()58if (rect) setSize({ width: rect.width, height: rect.height })59}, [])6061const onLayout = (e: LayoutChangeEvent) => {62const { width, height } = e.nativeEvent.layout63setSize((prev) => {64// for non-primitive states, compare values before firing a re-render65if (prev?.width === width && prev?.height === height) return prev66return { width, height }67})68}6970return (71<View ref={ref} onLayout={onLayout}>72{children}73</View>74)75}76```7778Use functional setState to compare—don't read state directly in the callback.79