簡體   English   中英

ReactNative 嵌套渲染函數。 關於對象和函數之間的“this”的問題

[英]ReactNative nested render functions. Question regarding `this` between objects and functions

這是我的困惑:

     constructor(props) {
    super(props);
  }

  hookNav(){
    console.log("work");
  }

  renderItem({ item, index }) {
    return (
      <TouchableOpacity style={{ margin: 9 }} onPress={this.hookNav}>
        <View
          style={{
            flex: 1,
            minWidth: 170,
            maxWidth: 223,
            height: 280,
            maxHeight: 280,
            borderRadius: 10,
          }}
        >
          <ImageBackground
            source={{
              uri: "https://picsum.photos/170/223",
            }}
            style={{ flex: 1 }}
            imageStyle={{ borderRadius: 10 }}
          >
            <Text
              style={{
                color: "white",
                position: "absolute",
                bottom: 20,
                right: 10,
                fontWeight: "bold",
                textShadowColor: "black",
                textShadowOffset: { width: -1, height: 1 },
                textShadowRadius: 10,
              }}
            >
              Topic
            </Text>
          </ImageBackground>
        </View>
      </TouchableOpacity>
    );
  }

  render(){
    return (
      <View style={{ marginBottom: 80, backgroundColor: "white" }}>
        <Header
          centerComponent={{ text: "test", style: { color: "orange" } }}
          rightComponent={{ icon: "add", color: "orange" }}
        />
        <FlatList
          numColumns={2}
          onEndReachedThreshold={0}
          onEndReached={({ distanceFromEnd }) => {
            console.debug("on end reached ", distanceFromEnd);
          }}
          contentContainerStyle={styles.list}
          data={[
            { key: "a" },
            { key: "b" },
            { key: "c" },
            { key: "d" },
            { key: "e" },
            { key: "f" },
          ]}
          renderItem={this.renderItem}
          ListHeaderComponent={
            <Text
              style={{ padding: 10, fontWeight: "bold" }}
            >
              Your Topics
            </Text>
          }
        />
      </View>
    );
  }
}

在上面的這段代碼中,當導航到這個頁面時,會立即拋出this.hookNav未定義的錯誤。

但是,當我將hookNav function 放在 state object 內部時,就像這樣

constructor(props) {
    super(props);
    state = {
      hookNav : function() {
       console.log("work please");
      }
    }
  }

並且在onPress里面的renderItem

const { hookNav} = this.state;
    return (
      <TouchableOpacity style={{ margin: 9 }} onPress={hookNav}>

這按預期工作。

據我了解, render已經可以通過this訪問組件的state 如果renderItem可以通過this訪問state object,為什么不能直接訪問this.hookNav()呢? 為什么 function 需要封裝在 object 中才能正常工作?

謝謝。

這是因為this在任何 Javascript function 中的值取決於 function 的調用方式。

在您的非工作示例中, this.hookNav位於renderItem方法內。 因此它將采用該方法的this ——正如我剛才所說,這取決於它的調用方式。 進一步檢查您的代碼表明renderItem方法不是由您的組件直接調用,而是作為FlatList組件的 prop(稱為renderItem )傳遞。 現在我不知道該組件是如何實現的(我從未使用過 React Native),但幾乎可以肯定它有時會調用 function - 當它調用時,它不能在你的組件的上下文中。 這是因為FlatList不可能知道 function prop 來自哪里,並且當它調用它時,它將被視為“普通” function,而不是在任何特定 ZA8CFDE63131BD59EB2AC9C68F 的上下文中。 所以它的this上下文不會像預期的那樣是你的組件實例,而只是全局 object - 它沒有任何hookNav方法。

在第二個示例中不會出現此問題,因為您只需訪問 function 作為this.state的一部分 - 沒有傳遞方法,如前一個示例中的renderItem ,這取決於內部this引用。 請注意,如果您的hookNav在其中引用this ,則情況並非如此。

this上下文的問題在 React 中很常見,但幸運的是有兩個通用的解決方案可以解決這個問題:

  1. 在組件的構造函數中綁定方法。 如果構造函數在第一個示例中包含語句this.renderItem = this.renderItem.bind(this); ,那么它會正常工作。 (請注意,在官方 React文檔中建議這樣做。)從技術上講,它是“最佳”解決方案(性能略好於其他選項)-但如果您有很多需要此類綁定的方法,則確實涉及相當多的樣板文件.

  2. 使用箭頭函數來定義方法。 而不是renderItem({ item, index }) {...} ,將其寫為renderItem = ({ item, index }) => {...} 這是有效的,因為箭頭函數采用了其詞匯 scope 的this ,這將是 class 本身 - 所以換句話說, this將始終引用組件實例,正如您幾乎總是想要的那樣。

如果這令人困惑,請不要擔心 - JS 中this關鍵字的行為對於 JS 初學者來說是一個常見的絆腳石,對於那些更有經驗的人來說通常也足夠了。 網上有很多很好的解釋可以揭開它的神秘面紗,其中我特別推薦這個

您必須將方法綁定this您的 class 中。 一種方法如下所示。

constructor(props){
  super(props);
  this.renderItem = this.renderItem.bind(this);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM