【问题标题】:What is the reason that function is not passed to a Button函数未传递给按钮的原因是什么
【发布时间】:2018-03-12 03:18:35
【问题描述】:

我知道 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

谁能向我解释为什么这段代码会这样?

【问题讨论】:

    标签: javascript reactjs relaymodern


    【解决方案1】:

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

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

    【讨论】:

    • 谢谢,我没想到绑定queryRender函数。这解决了我的问题。
    【解决方案2】:

    要扩展 Artur 和 Nicholas 的答案,您需要 bind() this 或使用箭头函数确保 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>
        )
      }
    }
    

    【讨论】:

    • 谢谢 Mike S。这实际上是非常有用的信息。
    【解决方案3】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      相关资源
      最近更新 更多