使用ref并访问HTMLElement来实现React Flow

时间:2018-01-05 19:26:48

标签: reactjs lambda flowtype

我正在为我的React项目添加流程。我按照流程反应参考部分中的说明进行操作。

我的问题是我在多个位置使用ref对象,所以如果我将它定义为可选,我会得到一个错误访问它,否则我从ref本身得到一个错误,因为它最初为null。

有没有一个解决方案,每次我想使用ref时都不需要检查?我可以告诉流程不对refs运行检查吗?

这里有一个简短的片段来解释我在做什么:

class AudioPlayer extends Component<Props> {
  player: ?HTMLAudioElement;

  componentWillUpdate(nextProps) {
    if (nextProps.duration && this.player.currentTime >= nextProps.duration) {
      this.reset();
    }
  }

  render() {
    const { src } = this.props;

    return (
      <audio
        className="track-audio"
        ref={audio => (this.player = audio)}
        loop
        onTimeUpdate={this.handleTimeUpdate}
        onLoadedMetadata={this.handleLoadMetadata}
      >
        <source src={src} />
      </audio>
    );
  }
}

考虑到我不想删除引用,除了检查!isEmpty(this.player)在哪里需要它之外,还有一个简单的解决方案吗?

1 个答案:

答案 0 :(得分:0)

The docs描述了为什么你应该使用一个可选的。你也可以像下面一样定义它(没有真正的优势,除非你发现它一目了然更容易理解):

class AudioPlayer extends Component<Props> {
  player: ?React.ElementRef<'audio'>;

  // ...rest
}

如果你发现这很烦人(我完全明白,相信我),你可以做一些不同的事情(我只列出我能想到的那些):

  1. 将该函数作为回调检查(不是超级优雅,但它完成了工作)

    class AudioPlayer extends Component<Props> {
      checkForPlayer(callback) {
        if (this.player) {
          return callback()
        }
      }
    
      componentWillUpdate(nextProps) {
        this.checkForPlayer(() => {
          if (nextProps.duration && this.player.currentTime >= nextProps.duration) {
            this.reset();
          }
        })
      }
    }
    
  2. 你可以做类似的事情,但有点像装饰者(我个人认为这一般来说更难阅读,但这是一个选择)

    class AudioPlayer extends Component<Props> {
      checkForPlayer(callback) {
        return (...args) => 
          if (this.player) {
            return callback(...args)
          }
        }
      }
    
      componentWillUpdate: this.checkForPlayer(nextProps => {
        if (nextProps.duration && this.player.currentTime >= nextProps.duration) {
          this.reset();
        }
      })
    }
    
  3. 每当您访问this.playerget(this.player, 'currentTime'))上的属性时,您都可以使用类似于(或完全)lodash.get的效用函数。除非你认为你会从以前的选项中看到很大的好处,否则我可能会坚持这样的事情。您会很快习惯语法,并且不需要额外的工作。你甚至可以做这样的事情(在查看我的答案后,这几乎是事后的想法。它可能并不比使用普通的效用函数更好):

    class AudioPlayer extends Component<Props> {
      playerProp(prop) {
        return this.player ? this.player[prop] : null
      }
    
      componentWillUpdate: this.checkForPlayer(nextProps => {
        if (nextProps.duration && this.playerProp('currentTime') >= nextProps.duration) {
          this.reset();
        }
      })
    }