在React ComponentDidMount中获取引用和附加事件侦听器的正确方法?

时间:2017-04-12 21:09:59

标签: reactjs

问题大致总结在代码段中的注释中。当我在this._setSize中绑定constructor时,它永远不会知道this.container - 即使在componentDidMount中调用时也是如此。我究竟做错了什么?谢谢!

export default class MyComponent extends React.Component {
  constructor () {
    super()
    this._setSize = this._setSize.bind(this)
  }

  componentDidMount () {
    const container = this.container // <div></div> :)
    this._setSize()
    window.addEventListener('resize', this._setSize)
  }

  componentWillUnmount () {
    window.addEventListener('resize', this._setSize)
  } 

  _setSize () {
    const container = this.container // undefined :(
    const containerSize = {
      x: container.offsetWidth,
      y: container.offsetHeight
    }
    this.setState({ containerSize })
  }

  render () {
    return (
      <div ref={node => this.container = node}>
      </div>
    )
  }
}

2 个答案:

答案 0 :(得分:4)

在每次重新渲染中,您正在创建并传递新的函数实例以设置容器引用。然后使用null调用上一个函数。因此,您可能会意外地将this.container设置为null

<div ref={node => this.container = node}>

当您在此处传递组件实例方法而不是内联函数时,它会在引用时调用一次,在组件卸载期间第二次调用null。 E.g:

// dont forget to bind it in constructor
onContainerRef (node) {
  // furthermore you can even check if node is not null
  // if (node) { ...
  this.container = node
} 

// ... in render
<div ref={this.onContainerRef}>

您可以在docs中阅读更多内容。

答案 1 :(得分:1)

我已修复您的代码,现在正在运行:see working DEMO

问题是什么?

componentWillUnmount () {
  window.addEventListener('resize', this._setSize)
}

您没有从window移除事件监听器,因为在componentWillUnmount中您有addEventListener而不是removeEventListener。如果您对组件进行了任何条件渲染,则还会调用resize事件_setSize

要说明此问题,请使用破解的演示并点击Toggle按钮并查看输出:see broken DEMO