Card nằm trong một vùng có padding, cạnh sidebar hoặc trong một cột. Chiều rộng cửa sổ không phải chiều rộng card. Nếu cần hiển thị thông tin đo đạc hoặc chọn tài nguyên theo vùng thực tế, hãy bắt sự kiện layout ngay trên View cần quan sát.
Bài đối chiếu tài liệu React Native 0.88 hiện hành ngày 02/11/2026. Demo đã được rà theo hợp đồng View.onLayout và LayoutEvent; hàm format số thuần JavaScript được chạy bằng Node 24.18.1. Chưa build React Native, chưa chạy Hermes, thiết bị hay phép đo native. Các case UI bên dưới là kế hoạch kiểm tra, không phải số đo thực tế.
Đo đúng object giao diện
onLayout được gọi khi mount và khi layout thay đổi. Callback đọc event.nativeEvent.layout; cấu trúc có width, height, x, y. Tọa độ x và y thuộc hệ tọa độ của component cha, không phải tọa độ tuyệt đối trên màn hình.
Một số đo layout cũng không đồng nghĩa toàn bộ vùng ấy đang nhìn thấy: component có thể bị che hoặc đang có animation. Tài liệu View lưu ý event có thể đến sau khi tính layout nhưng trước khi trạng thái mới thể hiện hoàn toàn trên màn hình. Chỉ dùng nó cho câu hỏi mà sự kiện này thật sự trả lời.
Demo giữ nhãn đo ở bên ngoài vùng được đo
Đặt ví dụ vào App.jsx của project React Native đang chạy:
import React, {useState} from 'react';
import {StyleSheet, Text, View} from 'react-native';
function formatSize(size) {
if (size === null) return 'Chưa có số đo';
return `${size.width.toFixed(1)} × ${size.height.toFixed(1)} dp`;
}
export default function App() {
const [size, setSize] = useState(null);
function handleLayout(event) {
const {width, height} = event.nativeEvent.layout;
setSize(previous => {
if (previous?.width === width && previous?.height === height) {
return previous;
}
return {width, height};
});
}
return (
<View style={styles.screen}>
<View style={styles.container}>
<View onLayout={handleLayout} style={styles.card}>
<Text style={styles.cardText}>Vùng đang được đo</Text>
</View>
<Text style={styles.label}>{formatSize(size)}</Text>
</View>
</View>
);
}
const styles = StyleSheet.create({
screen: {flex: 1, justifyContent: 'center', backgroundColor: '#f1f5f9'},
container: {paddingHorizontal: 24},
card: {height: 112, padding: 16, backgroundColor: '#dbeafe'},
cardText: {color: '#172554'},
label: {marginTop: 12, color: '#0f172a'},
});
Nhãn nằm cạnh card trong cây cha nên nội dung số đo không được dùng để gán ngược lại width cho card. Callback cũng giữ nguyên reference state nếu hai số không đổi. Đây là biện pháp giữ luồng dữ liệu rõ, không phải benchmark số lần render hay bằng chứng rằng mọi layout phức tạp đều không thể lặp.
Không nhân PixelRatio để đặt width
Các kích thước trong ví dụ là đơn vị layout dp. PixelRatio.getPixelSizeForLayoutSize chuyển kích thước layout sang số pixel nguyên, hữu ích khi yêu cầu ảnh nguồn đủ độ phân giải. Nó không có nghĩa phải lấy width từ onLayout rồi nhân mật độ trước khi đưa lại vào style.
Nếu API ảnh nhận kích thước pixel, bạn có thể dùng phép chuyển đổi ở ranh giới yêu cầu tài nguyên. Nhưng giữ constraint giao diện theo đơn vị layout; trộn hai hệ đơn vị sẽ làm khó giải thích vì sao card hoặc ảnh có kích thước khác ý định.
Cách kiểm tra trên project thật
Quan sát nhãn sau mount, rồi đổi chiều màn hình hoặc thay padding của container. Card phải phản ánh vùng cha hiện tại, còn nhãn ban đầu “Chưa có số đo” thể hiện state chưa nhận event. Không giả định state ngay sau render đầu đã có width khác 0.
Thử thay chiều cao card, tăng cỡ chữ hệ thống và đưa component vào vùng cột hẹp. Nếu chỉ cần flexbox chia không gian, đừng thêm state đo đạc để thay thế layout khai báo sẵn. Còn nếu thật sự cần đo, kiểm tra đúng View và tách phần kết quả khỏi các kích thước đang điều khiển View đó.
Node chỉ xác nhận hàm format xử lý null và số thập phân; nó không tạo LayoutEvent native. Khi tích hợp, chạy app trên các nền tảng mục tiêu và kiểm tra trường hợp animation nếu có. Số đo component giúp bạn trả lời câu hỏi về vùng thực tế, với điều kiện đọc đúng thời điểm và đúng hệ tọa độ.




