简体   繁体   English

函数未传递给Button的原因是什么

[英]What is the reason that function is not passed to a Button

I'm aware of JavaScript's scopes but probably I don't understand them fully because this code doesn't work. 我知道JavaScript的范围,但是可能我不太了解它们,因为此代码无法正常工作。

This code uses React and Relay Modern frameworks. 此代码使用React和Relay Modern框架。

There are 2 buttons, first one inside queryRender which is passed into Relay Modern QueryRenderer and second one afterwards (see function render ). 有2个按钮,第一个在内部的queryRender ,该按钮被传递到Relay Modern QueryRenderer然后第二个(请参见函数render )。 The second one is working, first one doesn't execute the clickTest function. 第二个正在工作,第一个不执行clickTest函数。 (This is simplified version of actual code) (这是实际代码的简化版本)

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>
    )
  }
}

The query variable is defined, I just didn't include it in that excerpt. query变量已定义,我只是未在该摘录中包括它。

When I substitue first button's onClick function with an anonymous one 当我用匿名按钮替换第一个按钮的onClick函数时

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

then I get such error: Uncaught TypeError: _this2.clickTest is not a function 然后我得到这样的错误:未捕获的TypeError:_this2.clickTest不是一个函数

Can anyone explain to me why this code behaves the way it does? 谁能向我解释为什么这段代码会如此运行?

In javascript, the meaning of this isn't determined when a function is created , but rather when it is invoked . 在JavaScript中,的含义this创建函数时没有确定,而是被调用时。 When QueryRenderer invokes your queryRender function, it doesn't know that it needs to invoke it in the context of your class, so this will not be referring to what you think it's referring to. 当QueryRenderer调用您的queryRender函数时,它不知道需要在您的类的上下文中调用它,因此this将不会指向您认为的对象。

You'll either need to bind your queryRender function, much like you're doing with your clicktest function in the constructor, or you'll need to redesign queryRender so it doesn't need a reference to this . 你要么需要绑定你的queryRender功能,就像你与你的clicktest功能在构造函数中做什么,或者你需要重新设计queryRender所以它并不需要参考this

To expand upon both Artur and Nicholas' answers, you either need to bind() this or use an arrow function to make sure that this is referring to the component itself. 要扩展Artur和Nicholas的答案,您要么需要bind()这个,要么使用箭头函数来确保this是指组件本身。 You already have the bind method down, here's en example of the arrow function which gets rid of the need to bind because arrow functions don't actually bind a this value, they use their parents scope instead... 您已经使用了bind方法,这是arrow函数的en示例,该示例摆脱了绑定的需要,因为arrow函数实际上并不绑定此值,而是使用其父范围。

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>
    )
  }
}

Arrow function doesn't create new scope and its scope is enclosing execution context, in this case it's QueryRenderer scope where you don't have this function. Arrow函数不会创建新的作用域,它的作用域包含执行上下文,在这种情况下,它是QueryRenderer作用域,而您没有此功能。 When you pass it as simple function then the scope will be undefined or not, I don't know what Button does inside. 当您将其作为简单函数传递时,范围将是不确定的或不确定的,我不知道Button在做什么。 I haven't used Rely and not sure you can refer to component from Rely render method. 我没有使用过Rely,并且不确定您可以从Rely渲染方法中引用组件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM