所以我有一个组件,它被一个组件包装,该组件有一个引用:
const viewRef = useRef(null);
...
<View ref={ viewRef }>
该组件还具有在按下时触发的功能
// locationX is the location of tapping relative to <View>
const tapSliderGesture = (locationX) => {
// we need the ViewRef to measure its size (width) and position relative to screen (px)
viewRef.current.measure((fx, fy, width, height, px) => {
const location = Math.round(((locationX - px) / width) * steps);
if (location !== state) {
setState(location);
}
});
};
...
<View ref={ viewRef } onResponderMove={ (evt) => { tapSliderGesture(evt.nativeEvent.locationX); } }>
但是,在 android 上,ViewRef.current
在tapSliderGesture
内部始终为空,有趣的是,ViewRef.current
组件内和tapSliderGesture
外部都不为空。
完整示例如下:
const AddSlider = ({setState, state, steps}) => {
const viewRef = useRef(null);
console.log('On render', viewRef.current); // prints after every re-render
// viewRef.current is not null after a render is triggered in the component
const tapSliderGesture = (locationX) => {
console.log(viewRef.current); // on iOS this prints the ref object
// on Android it prints null
viewRef.current.measure((fx, fy, width, height, px) => {
const location = Math.round(((locationX - px) / width) * steps);
if (location !== state) {
setState(location);
}
});
};
return (
<View
ref={ viewRef }
onResponderMove={ (evt) => { tapSliderGesture(evt.nativeEvent.locationX); } }
onResponderGrant={ (evt) => { tapSliderGesture(evt.nativeEvent.locationX); } }
>
<Slider .../>
</View>
);
};
所以问题是 android 有某种优化来改变 DOM 层次结构树。答案是在我的视图中添加collapsable: false
道具,因此:
<View ref={ viewRef } collapsable={ false } .../>
那修复了它...
https://github.com/facebook/react-native/issues/3282
提到的另一种解决方法是向视图节点添加一个空的onLayout
道具:onLayout={() => {}}