2017-09-30 43 views
0

我知道JavaScript的作用域,但可能我完全不理解它們,因爲這段代碼不起作用。函數不傳遞給Button的原因是什麼

此代碼使用React和Relay Modern框架。

有2個按鈕,第一個內部queryRender,其被傳遞到中繼現代QueryRenderer和第二個之後(見函數render)。第二個工作正常,第一個不執行clickTest函數。 (這是簡化的實際代碼版本)

class Candidates extends Component { 
    static propTypes = { 
    viewer: PropTypes.object 
    } 

    constructor (props) { 
    super(props) 
    this.clickTest = this.clickTest.bind(this) 
    } 

    clickTest() { 
    console.log('click works') 
    }  

    queryRender ({error, props}) { 
    if (error) { 
     return <pre>{error.message}</pre> 
    } else if (props) { 
     return (
     <div> 
      <Button onClick={this.clickTest}>this DOESN'T work</Button> 
     </div> 
    ) 
    } 
    return <Loader active>Loading...</Loader> 
    } 

    render() { 
    return (
     <div> 
     <QueryRenderer 
      environment={environment} 
      query={query} 
      render={this.queryRender} 
     /> 
     <Button onClick={this.clickTest}>this works</Button> 
     </div> 
    ) 
    } 
} 

query該變量被定義,我只是沒有包括在該摘錄。

當我第一次substitue按鈕的onClick功能與匿名一個

<Button onClick={() => this.clickTest()}>this DOESN'T work</Button> 

然後我得到這樣的錯誤:遺漏的類型錯誤:_this2.clickTest不是一個函數

任何人都可以向我爲什麼這個代碼解釋行爲的方式呢?

回答

1

在JavaScript中,沒有確定的this含義當一個功能是創建,而是當它是調用。當QueryRenderer調用你的queryRender函數時,它不知道它需要在你的類的上下文中調用它,所以this不會指你認爲它指的是什麼。

您需要綁定您的queryRender函數,就像您在構造函數中使用clicktest函數一樣,或者您需要重新設計queryRender,因此它不需要對this的引用。

+0

謝謝,我沒想過綁定'queryRender'函數。這解決了我的問題。 – Pawel

0

箭頭函數不會創建新的作用域,它的作用域將圍繞執行上下文,在這種情況下,它的作用域是QueryRenderer,而您沒有這個函數。當你將它作爲簡單函數傳遞時,範圍將不確定或不確定,我不知道里面有什麼Button。我沒有使用Rely,也不確定你可以從Rely render方法中引用組件。

1

爲了擴大Artur和Nicholas的答案,您需要輸入bind()或使用箭頭功能來確保this指的是組件本身。您已經綁定方法了,這裏是連接例子擺脫的結合,因爲箭頭的功能實際上並不綁定這個值需要箭頭的功能,他們用自己的父母,而不是範圍...

class Candidates extends Component { 
    static propTypes = { 
    viewer: PropTypes.object 
    } 

    constructor (props) { 
    super(props) 
    this.clickTest = this.clickTest.bind(this) 
    } 

    clickTest() { 
    console.log('click works') 
    }  

    queryRender = ({error, props}) => { 
    if (error) { 
     return <pre>{error.message}</pre> 
    } else if (props) { 
     return (
     <div> 
      <Button onClick={this.clickTest}>this DOESN'T work</Button> 
     </div> 
    ) 
    } 
    return <Loader active>Loading...</Loader> 
    } 

    render() { 
    return (
     <div> 
     <QueryRenderer 
      environment={environment} 
      query={query} 
      render={this.queryRender} 
     /> 
     <Button onClick={this.clickTest}>this works</Button> 
     </div> 
    ) 
    } 
} 
+0

感謝Mike S.這實際上是非常有用的信息。 – Pawel

相關問題