0

我知道 JavaScript 的作用域,但我可能不完全理解它们,因为这段代码不起作用。

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

有 2 个按钮,第一个在内部queryRender传递到 Relay Modern 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变量已定义,我只是没有将其包含在该摘录中。

当我用匿名函数替换第一个按钮的 onClick 函数时

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

然后我得到这样的错误: Uncaught TypeError: _this2.clickTest is not a function

谁能向我解释为什么这段代码的行为方式如此?

4

3 回答 3

1

在 javascript 中, 的含义this不是在创建函数时确定的,而是在调用它时确定的。当 QueryRenderer 调用您的 queryRender 函数时,它不知道它需要在您的类的上下文中调用它,因此this不会引用您认为它所指的内容。

您需要绑定您的 queryRender 函数,就像您在构造函数中使用 clicktest 函数一样,或者您需要重新设计 queryRender 以便它不需要引用this.

于 2017-09-30T11:04:38.787 回答
1

要扩展 Artur 和 Nicholas 的答案,您要么需要这样做,要么bind()使用箭头函数来确保它this指的是组件本身。您已经有了 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>
    )
  }
}
于 2017-09-30T14:16:48.377 回答
0

箭头函数不会创建新的作用域,它的作用域是封闭的执行上下文,在这种情况下,它是QueryRenderer 你没有这个函数的作用域。当你将它作为简单函数传递时,范围将是未定义的,我不知道Button里面有什么。我没有使用过 Rely,不确定您是否可以从 Rely 渲染方法中引用组件。

于 2017-09-30T11:26:13.147 回答