버그 내용
<View />
의 크기 및 위치 정보를 알아내는 방법은 두 가지가 있다. 하나는 onLayout
콜백을 쓰는 것.
const SomeComp1 = () => {
return (
<View
onLayout={(evt) => {
// evt.nativeEvent.layout.width
// evt.nativeEvent.layout.height
// evt.nativeEvent.layout.x
// evt.nativeEvent.layout.y
}}
>
{/* ... */}
</View>
);
};
다른 하나는 ref.current.measure
메서드를 쓰는 것.
const SomeComp2 = () => {
const ref = useRef();
const onPressMeasure = () => {
ref.current.measure((x, y, width, height, pageX, pageY) => {
// ...
});
};
return (
<>
<View ref={ref}>
{/* ... */}
</View>
<Button onPress={onPressMeasure} title="measure" />
</>
);
};
(둘의 차이점은 공식 문서를 참고하자)
그런데 ref.current.measure
메서드에는 한 가지 버그가 있다. 안드로이드 환경에서, 모든 값이 undefined
로 반환되는 현상이 그것이다.
const SomeComp2 = () => {
const ref = useRef();
const onPressMeasure = () => {
ref.current.measure((x, y, width, height, pageX, pageY) => {
console.log(x); // undefined console.log(y); // undefined console.log(width); // undefined console.log(height); // undefined console.log(pageX); // undefined console.log(pageY); // undefined });
};
return (
<>
<View ref={ref}>
{/* ... */}
</View>
<Button onPress={onPressMeasure} title="measure" />
</>
);
};
해결 방법
React Native 깃헙 이슈에 20년 8월에 등록된, 긴 역사를 갖고 있는 버그이다. 해결법은 간단한데 <View />
에 collapsable
prop 을 false
로 지정해주는 것이다.
const SomeComp2 = () => {
const ref = useRef();
const onPressMeasure = () => {
ref.current.measure((x, y, width, height, pageX, pageY) => {
console.log(x); // not undefined console.log(y); // not undefined console.log(width); // not undefined console.log(height); // not undefined console.log(pageX); // not undefined console.log(pageY); // not undefined });
};
return (
<>
<View
ref={ref}
collapsable={false} >
{/* ... */}
</View>
<Button onPress={onPressMeasure} title="measure" />
</>
);
};
원인
collapsable
prop 공식 문서에는 아래와 같이 설명이 있다.
Views that are only used to layout their children or otherwise don't draw anything may be automatically removed from the native hierarchy as an optimization. Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy.
간단히 번역해보면 아래와 같다.
성능 최적화를 위해, 안드로이드 환경에서
<View />
는 레아이웃을 위해서만 쓰이고 실제로는 렌더링되지 않는다. 그러니 필요하다면 값을false
로 지정해 렌더링하게 해라.
즉, 실제로 렌더링되지 않았기 때문에 크기 및 위치 정보 값이 없었던 것이다.
의견
내 생각에 React Native 측에서 이 버그를 방치하고 있는 이유는 아마도 버그가 아니라고 생각하기 때문인 것 같다.
"안드로이드 특성 상 <View />
가 그렇게 구현되는 것은 자연스러운 것이고, collapsable
prop 문서에도 해당 맥락에 대한 내용이 설명되어 있으니 문제 없는 이슈 혹은 문제가 있더라도 우선순위가 떨어지는 이슈다."
라고 말이다. (어디까지나 내 추측이다.)
하지만 그렇게 말하려면 최소한 measure
메서드의 공식 문서에도 관련된 이야기를 넣어줘야 하는 게 아닌가 싶다. <View />
컴포넌트의 모든 prop 을 알고 사람이 아닌 이상, 이 버그를 맞닥뜨렸을 때 원인이나 해결책을 알 수 있을 리 없다.