React Native中navigationOptions调用this.refs报undefined is not object错误求助
你遇到的undefined is not object错误,核心原因是**onBack方法的this上下文丢失**了,咱们一步步拆解问题并解决:
问题根源
当你在componentDidMount里把this.onBack通过setParams传递给navigation时,这个方法的this默认不会绑定到组件实例。等到在headerLeft的点击事件中调用它时,this已经变成了undefined,自然就访问不到this.refs了。
解决方案
这里有几种靠谱的解决方式,你可以根据习惯选择:
1. 用箭头函数定义onBack(最简便)
箭头函数会自动绑定组件实例的this,直接修改onBack的定义:
onBack = (canGoBack) => { console.log(canGoBack); if(canGoBack){ this.refs[WEBVIEW_REF].goBack(); } }
这样不管怎么传递这个方法,this都会指向你的组件实例,就能正常访问this.refs了。
2. 在setParams时手动绑定this
如果不想改方法定义,也可以在传递的时候给onBack绑定组件的this:
componentDidMount() { // 绑定this后再传入params this.props.navigation.setParams({goBack: this.onBack.bind(this)}); this.props.navigation.setParams({canGoBack: this.state.canGoBack}); Keyboard.dismiss(); }
这种方式会强制让onBack执行时的this指向组件实例。
3. 使用React.createRef替代字符串refs(推荐最佳实践)
字符串refs已经被React官方标记为废弃,更推荐用createRef来创建引用,同时也能避免一些上下文问题:
首先在组件构造函数里创建ref:
constructor(props) { super(props); this.webViewRef = React.createRef(); this.state = { canGoBack: false }; }
然后在你的WebView组件上引用它:
<WebView ref={this.webViewRef} />
最后修改onBack方法:
onBack = (canGoBack) => { console.log(canGoBack); if(canGoBack){ this.webViewRef.current.goBack(); } }
这种方式不仅解决了当前的this问题,还符合React的最新规范,后续维护也更稳妥。
额外小提示
在onNavigationStateChange里更新state后,最好不要直接用this.state.canGoBack去setParams,因为setState是异步的,可能拿到的还是旧值。可以改成这样:
onNavigationStateChange(navState) { const canGoBack = navState.canGoBack; this.setState({ canGoBack }); this.props.navigation.setParams({ canGoBack }); }
直接用navState里的最新值,避免异步更新带来的问题。
内容的提问来源于stack exchange,提问作者Mizlul

