React Native iOS横竖屏切换触发scrollView.scrollTo调用崩溃报错
问题定位
错误TypeError: null is not an object(evaluating '_this.scrollView.scrollTo')的触发根因是横竖屏切换后,原有ScrollView实例被销毁,ref被置空,之前注册的延时回调触发时访问了不存在的实例,具体触发逻辑:
- 你在
componentDidMount中注册了15秒的延时任务,回调持有当前组件的上下文 - iOS横竖屏切换时,React Native默认会触发组件重新挂载,旧的ScrollView实例被销毁,
this._scrollView被置为null - 15秒后延时回调触发,直接调用
this._scrollView.scrollTo就会抛出空引用错误 - 额外隐患:你在挂载时读取的
dim.width是固定值,横竖屏切换后屏幕宽高会交换,就算实例未销毁,滚动偏移量也不符合预期
修复方案
分步骤修复,从根本解决崩溃问题同时兼容横竖屏切换场景:
- 调用
scrollTo前增加非空校验,同时在组件卸载时清理延时任务,避免访问已销毁的实例
componentDidMount() { let scrollValue = 0; const dim = Dimensions.get('screen'); // 存储定时器ID用于后续清理 this.scrollTimer = setTimeout(() => { // 先判断ScrollView实例是否存在再调用方法 if (this._scrollView) { scrollValue = scrollValue + dim.width; this._scrollView.scrollTo({x: scrollValue}); } }, 15000); } componentWillUnmount() { // 组件卸载时清理未执行的定时器 if (this.scrollTimer) { clearTimeout(this.scrollTimer); } }
- 如需适配横竖屏切换后的滚动距离,增加屏幕尺寸监听实时更新宽度
componentDidMount() { // 初始化存储屏幕宽度 this.screenWidth = Dimensions.get('screen').width; // 监听屏幕尺寸变化(横竖屏切换会触发) this.dimensionListener = Dimensions.addEventListener('change', ({screen}) => { this.screenWidth = screen.width; }); let scrollValue = 0; this.scrollTimer = setTimeout(() => { if (this._scrollView) { scrollValue = scrollValue + this.screenWidth; this._scrollView.scrollTo({x: scrollValue}); } }, 15000); } componentWillUnmount() { if (this.dimensionListener) { this.dimensionListener.remove(); } if (this.scrollTimer) { clearTimeout(this.scrollTimer); } }
- 额外注意:你提供的示例代码存在语法问题,
componentDidMount缺少方法括号,应写为componentDidMount() {},ScrollView标签也缺少闭合标记,实际开发中需要修正语法错误。
内容的提问来源于stack exchange,提问作者Ravikiran Avasarala
相关产品推荐
相关产品推荐

