使用带有Flow的ref函数 - 无法在可能未定义的值上访问属性

时间:2018-02-05 23:58:35

标签: reactjs flowtype

我正在向现有项目添加Flow。我的普通道具类型检查工作得很好,但我无法弄清楚为什么我的搜索输入ref函数存在问题。我已经按照Flow文档并使用searchInput: ?HTMLInputElement设置了一行,但这只会导致更多错误。这是我正在使用的代码的精简版本,其中包含所有相关的this.searchInput引用:

// @flow
import React, { Component } from 'react'

class DataTable extends Component {

    searchInput: ?HTMLInputElement

    loadNextPage = () => {
        const isFetching = this.props.isFetching
        const number = this.props.paginationNumber
        const links = this.props.links
        if (!isFetching && links.next && this.searchInput.value === '') {
            this.props.fetchData(number + 1, 10)
        }
    }
    handleKeyDown = e => {
        if (e.keyCode === 13) {
            this.search(e.target.value)
        }
    }
    search = text => {
        this.props.searchData(1, 1, text)
        this.forceUpdate()
    }
    handleSearch = () => {
        this.search(this.searchInput.value)
    }
    handleClear = () => {
        this.clearSearch()
    }
    clearSearch = () => {
        const number = this.props.paginationNumber
        if (this.searchInput.value !== '') {
            this.searchInput.value = ''
            this.props.clearSearch()
            this.props.fetchData(number + 1, 10)
        }
    }

    render() {
            <Flex justify="center">
            <Box>
                <input
                type="search"
                ref={ input => this.searchInput = input }
                onKeyDown={ this.handleKeyDown }
                />
                <PrimaryButton
                onClick={ this.handleSearch }>
                SEARCH
                </PrimaryButton>
                <PrimaryButton 
                onClick={ this.handleClear }>
                CLEAR
                </PrimaryButton>
            </Box>
            </Flex>
        )
    }

这会对this.searchInput.value的每次引用产生以下错误:

this.search(this.searchInput.value)
^^^^^ property `value`. Property cannot be accessed on possibly null value
this.search(this.searchInput.value)
 ^^^^^^^^^^^^^^^^ null or undefined

我也尝试从?删除?HTMLInputElement,但这给了我这个错误:

ref={ input => this.searchInput = input }
^^^^^ null. This type is incompatible with
ref={ input => this.searchInput = input }
^^^^^^^^^^^^^^^^ HTMLInputElement

任何想法如何让这些类型检查通过?

2 个答案:

答案 0 :(得分:3)

问题是您是否尝试访问value某些类型的内容。原因就在同一页上:

  

?中的?HTMLButtonElement非常重要。在上面的例子中   ref的第一个参数将是HTMLButtonElement | null,就像React一样   当组件卸载时,使用null调用您的ref回调。也,   在React拥有之前,button上的MyComponent属性不会被设置   完成渲染。在此之前,您的button引用将不确定。   保护自己免受这些情况的影响并使用?(如   ?HTMLButtonElement)保护自己免受错误。

看起来有点矫枉过正,但绝对可以让你免受随机问题的困扰。您应该进行以下更改:

class DataTable extends Component {
  searchInput: ?HTMLInputElement

  loadNextPage = () => {
      const isFetching = this.props.isFetching
      const number = this.props.paginationNumber
      const links = this.props.links
      if (!isFetching && links.next && this.searchInput && this.searchInput.value === '') {
          this.props.fetchData(number + 1, 10)
      }
  }

  handleSearch = () => {
    if (!this.searchInput) {
      return
    }

    this.search(this.searchInput.value)
  }

  clearSearch = () => {
    const number = this.props.paginationNumber;
    if (this.searchInput && this.searchInput.value !== '') {
      this.searchInput.value = ''
      this.props.clearSearch()
      this.props.fetchData(number + 1, 10)
    }
  }

  // ...etc
}

您尝试访问某个属性null的属性,这就是您查看错误的原因。你只需要检查是否存在。

答案 1 :(得分:0)

我无法保证为什么会发生这种情况,但我认为这是因为ref是因为在调用ref回调之前正在执行流,因此在第一次渲染/挂载时ref等于null。

解决这个问题的一种方法是:

searchInput: any

这不是最好的解决方案,因为您并没有准确指定类型,但您也可以尝试做类似的事情

searchInput: HTMLInputElement | null 

无法保证第二种方法对您有用。有时我觉得使用任何类型是不可避免的,只是为了节省很多时间。我强烈建议尽可能避免它......