1. 程式人生 > >React-native踩坑日記(一)

React-native踩坑日記(一)

建立頁面跳轉時報錯 undefined is not an object (this.props.navigation.navigate

學習 React-native 的第一個心得就是要做好踩坑的準備,之前剛入手的時候瘋狂紅屏,於是各種百度, 終於可以正常執行。 但是還是會經常遇到一些極其難受的問題,今天碼程式碼的時候用的是官方文件推薦的一款導航欄的包,我引用的時候,進行頁面跳 轉的時候總是會紅屏報錯

undefined is not an object (this.props.navigation.navigate

上網搜了很多處理方法,但是也都沒什麼作用;於是開始自己探索,終於發現瞭解決辦法。

我的軟體模組是由一個 Home 路由,繫結的 App 模組,App 模組裡面又渲染一個 Tab 模組,Tab 模組之內又渲染了一個 ListView, 然後我的目的是通過點選 ListView 的 Item,進行頁面跳轉。

方法如下:

當繫結的路由模組想要通過該元件內的一個子元件的點選事件到達另一個路由的時候,this.props.navigation,裡面的 this 是需要我們由最高模組一層一層傳遞過來,也就是說我上面的 App->Tab->ListView 需要將 this 一層一層傳遞過來。

下面我們通過程式碼來解釋一下:

Route;
export default createStackNavigator(
  {
    Home: App,
    Details: Details
  },
  {
    initialRouteName: "Home"
  }
);
App.js;
class App extends Component {
  static navigationOptions = {
    title: "電影列表"
  };
  render() {
    return (
      <View style={styles.container}>
        <Tab navigation={this.props.navigation} />
      </View>
    );
  }
}
Tab.js
render() {
    return (
      <TabNavigator
tabBarStyle={styles.tab}>
<TabNavigator.Item selected={this.state.selectedTab === "home"} title="列表" titleStyle={styles.tabText} selectedTitleStyle={styles.selectedTabText} renderIcon={() => ( <Image source={require("../images/Other-grey.png")} style={styles.icon} /> )} renderSelectedIcon={() => ( <Image style={styles.icon} source={require("../images/Other.png")} /> )} onPress={() => this.setState({ selectedTab: "home" })} > <MovieList navigation={this.props.navigation} /> </TabNavigator.Item> </TabNavigator> ); }

可以看到我在 Tab 的 render 裡面渲染了一個 MoveList 模組,然後 Tab 中的 navigation={this.props.navigation}已經在>App.js 中傳過來了,現在我們再用 MovieList navigation={this.props.navigation}這樣的程式碼,將這個屬性再傳給>Movelist,最後在 MoveList 這個模組中,如果我們直接用 onPress={() => this.props.navigation.navigate(‘Details’) 依然會報錯,這是因為我們一層一層傳輸過來的this,並沒有被引用到,也就是說這個 onPress 裡面直接用箭頭函式寫的 this,並不是我們傳輸過來的this,我們可以通過一個 bind 屬性,將傳輸過來的 this 繫結到一個自定義函式中。

接下來我們看一眼 MoveList 中引用這個屬性的程式碼

MoveList.js
toDetail(movie) {
    this.props.navigation.navigate("Details");
  }
  renerMovieList(movie) {
    return (
      <TouchableNativeFeedback onPress={this.toDetail.bind(this)}>
        <View style={styles.item}>
          <View style={styles.itemImage}>
            <Image source={{ uri: movie.images.large }} style={styles.Image} />
          </View>
        </View>
      </TouchableNativeFeedback>
    );
  }

下面展示一下執行之後的結果: