2017-09-30 29 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

相关问题