Very often when coding in react native you might need to know container’s width. For this purpose, react-native provides onLayout
property of View
component:
onLayout
Invoked on mount and layout changes with:
{nativeEvent: { layout: {x, y, width, height}}}
This event is fired immediately once the layout has been calculated, but the new layout may not yet be reflected on the screen at the time the event is received, especially if a layout animation is in progress.
Typical usage example you can find online will look like this:
import React, { useState, useCallback } from "react"; import { View } from "react-native"; const MyComponent = () => { const [measuredWidth, setMeasuredWidth] = useState(0); const onLayout = useCallback( ({ nativeEvent: { layout: { width } } }) => { setMeasuredWidth(width); }, [] ); return ( <View onLayout={onLayout}> <View style={{width: measuredWidth}}> /*Some content that depends on width*/ </View> </View> ); }; export default MyComponent;
This code, however, might introduce unwanted flickering (internal content renders without determined width for a split second). Problem is more visible when rendering a chart, or some heavy component. Here is a slightly improved version that helps to prevent / minimize negative visual effects:
import React, { useState, useCallback } from "react"; import { View } from "react-native"; const MyComponent = () => { const [measuredWidth, setMeasuredWidth] = useState(null); const onLayout = useCallback( ({ nativeEvent: { layout: { width } } }) => { setMeasuredWidth(width); }, [] ); return ( <> <View onLayout={onLayout} /> {typeof measuredWidth === "number" && ( <View style={{width: measuredWidth}}> /*Some content that depends on width*/ </View> )} </> ); }; export default MyComponent;
Main difference is that I use empty View
for measurement, which is faster and content does not interfere with measurement in any way. Additionally, I render width-dependent content only when width is measured.
This helps to prevent flickering, and I even noticed some performance gain on old device.
Featured image source – pxhere.com