undefined is not an object (evaluating 'this.props.navigator.push')

這個問題困擾了我多時,重點不是我不知道緣由,而是不知道怎麼解決,花費了我很長時間,可是最終解決了,如今把整個過程記錄在這裏:javascript


react native 中的navigator組件的使用:html

  • 引入
import{ Navigator } from 'react-native'
  • 在頁面中使用
<Navigator
         initialRoute={{ id: 'Home', params: { message: 'travel頁面' } }}
         configureScene={(route) => {
             if (route.sceneConfig) {
                 return route.sceneConfig
             }
             return Navigator.SceneConfigs.FloatFromRight
         } }
         renderScene={this.renderView}
   />

具體能夠移步這裏 下面開始講述個人踩坑之旅 能夠下載個人項目源碼進行詳細查看,github地址java

初始化頁面代碼:

import * as React from "react";
import {
    AppRegistry,
    StyleSheet,
    Text,
    View,
    Navigator,
    NavigatorIOS
} from 'react-native';
import { HomeView, SpotsView, TravelsView, WriteView, UserView } from './views'

class myApp extends React.Component<any, any>{
    constructor(props: any) {
        super(props)
    }
    /**
     *頁面跳轉
     */
    renderView(route: any, navigator: any) {
        let routeId = route.id;
        switch (routeId) {
            case 'Home':
                return (
                    <HomeView navigator={navigator} />
                );
            case 'Spots':
                return (
                    <SpotsView {...route.params} navigator={navigator} />
                )
            case 'Travels':
                return (
                    <TravelsView {...route.params} navigator={navigator} />
                )
            case 'Write':
                return (
                    <WriteView {...route.params} navigator={navigator} />
                )
            case 'User':
                return (
                    <UserView {...route.params} navigator={navigator} />
                )
        }
    }


    render() {
        return (
            <Navigator
                initialRoute={{ id: 'Home', params: { message: 'home頁面' } }}
                configureScene={(route) => {
                    if (route.sceneConfig) {
                        return route.sceneConfig
                    }
                    return Navigator.SceneConfigs.FloatFromBottom
                } }
                renderScene={(route, navigator) => this.renderView(route, navigator)}
                />
        )
    }
}

export default () => myApp

(2)定義了一個footerBar組件react

import * as React from 'react'
import { View, Text, Image, Touchable, TouchableOpacity, Navigator, Dimensions, StyleSheet } from 'react-native'
import * as CONST from '../../CONST'
import { HomeView } from '../../views/home/home.view'
import { SpotsView } from '../../views/spots/spots.view'
import { TravelsView } from '../../views/travels/travels.view'
import { WriteView } from '../../views/write/write.view'
import { UserView } from '../../views/user/user.view'

/**圖片的統一引入 */
const homeImg = require('../../../public/index.png')
const spotsImg = require('../../../public/spots.png')
const writeImg = require('../../../public/write.png')
const travelImg = require('../../../public/travels.png')
const userImg = require('../../../public/user.png')

export class FooterBar extends React.Component<any, any>{
    constructor(props: any) {
        super(props)

    }

    /**
     *頁面跳轉
     */
    navigator() {
        this.props.navigator.push({
            id: 'User',
            params: {
                messgage: 'User page'
            }
        })
    }

    render() {
        return (
            <View style={[styles.footerBarContainer, { width: CONST.WIDTH }]}>
                <TouchableOpacity style={[styles.footerBarItem, { width: CONST.WIDTH / 5 }]}>
                    <Image source={homeImg} style={styles.itemImg} />
                    <Text style={styles.itemText}>首頁</Text>
                </TouchableOpacity>
                <TouchableOpacity style={[styles.footerBarItem, { width: CONST.WIDTH / 5 }]}>
                    <Image source={spotsImg} style={styles.itemImg} />
                    <Text style={styles.itemText}>景點</Text>
                </TouchableOpacity>
                <TouchableOpacity style={[styles.footerBarItem, { width: CONST.WIDTH / 5 }]}>
                    <Image source={writeImg} style={styles.itemImg} />
                    <Text style={styles.itemText}>記錄</Text>
                </TouchableOpacity>
                <TouchableOpacity style={[styles.footerBarItem, { width: CONST.WIDTH / 5 }]}>
                    <Image source={travelImg} style={styles.itemImg} />
                    <Text style={styles.itemText}>遊記</Text>
                </TouchableOpacity>
                <TouchableOpacity style={[styles.footerBarItem, { width: CONST.WIDTH / 5 }]} onPress={this.navigator}>
                    <Image source={userImg} style={styles.itemImg} />
                    <Text style={styles.itemText}>個人</Text>
                </TouchableOpacity>
            </View>
        )
    }
}

而後在其中一個頁面的代碼以下:git

import * as React from 'react'
import { View, Text, Image, Dimensions ,Navigator} from 'react-native'
import { FooterBar } from '../../components'

export class UserView extends React.Component<any, any>{

    constructor(props: any) {
        super(props)
    }
    render() {
        console.warn(this.props, 'uuuu')
        return (
            <View>
                <Text>this is the user page</Text>
                <FooterBar />
            </View>
        )
    }
}

可是在運行項目的時候,老是提示錯誤:undefined is not an object (evaluating 'this.props.navigator.push')github

google了一下,是由於沒有正確綁定this對象的緣由,因而按照網上的解決方案試了一下:npm

  • 方案一:將函數自動綁定this對象
<TouchableOpacity style={[styles.footerBarItem, { width: CONST.WIDTH / 5 }]} onPress={this.navigator.bind(this)}>
  • 方案二:在constructor函數上進行this綁定
constructor(props: any) {
        super(props)
        this.navigator = this.navigator.bind(this)
 }
  • 方案三:使用Es6的箭頭函數
onPress={()=>this.navigator}
  • 方案四:安裝autobind-decorator 模塊,詳細步驟能夠移步這裏

可是這四種方案都以失敗了結,那個錯誤仍是穩妥當當地出現,我在facebookreact-native github上提了issue也沒人,鳥,issue地址react-native

最後的最後,我仔細地研究了一下facebook的f8app這個開源項目的navigator使用,最終發現是由於我在使用footerBar組件的時候沒有傳入navigator propsapp

因而作了以下更改:函數

  • 在footerBar組件中加入props聲明:
export interface propsType {
    navigator: Navigator
}
  • 當其餘頁面使用這個組件的時候,傳入navigator
<FooterBar navigator={this.props.navigator} />

自此,問題解決了,雖然是一個不太難的bug,可是仍是記錄一下,在這過程當中學到了不少

相關文章
相關標籤/搜索