Как выбрать наиболее эффективный способ вызова функции-обработчика в React? - PullRequest
0 голосов
/ 07 мая 2020

Я все еще новичок в React, но понимаю, что есть два общих способа определения функций обратного вызова:

// Method 1
private handleInputChange = (event) => {
    this.setState({name: event.target.value});
}
// Method 2
private handleInputChange(event){
    this.setState({name:event.target.value});
}

И внутри элемента DOM (для этого примера давайте используем <input>) , обработчик может быть вызван различными методами, например:

// Method 1
<input
    type="text"
    onChange={this.handleInputChange}
/>

// Method 2
<input
    type="text"
    onChange={(e) => this.handleInputChange(e)}
/>

// Method 3 (assume the function don't have parameters)
<input
    type="text"
    onChange={this.handleNewThing()}
/>

Мой вопрос: какой метод лучше использовать? Я действительно так запутался во всех этих методах. А потом я вижу людей, включая bind() по какой-то причине ??

1 Ответ

2 голосов
/ 07 мая 2020

Вы правы, есть множество способов обрабатывать обработчики (ba-dum-tss). React существует уже некоторое время, и лицо JavaScript за это время совсем немного изменилось.

В документации React есть целая страница, посвященная обработке событий , но тем не менее вот сравнение некоторых способов обработки обратных вызовов:

class MyComponent extends React.Component {
  constructor (props) {
    super(props)
    this.boundHandleClick = this.boundHandleClick.bind(this)
  }

  arrowHandleClick = (event) => { this.props.onClick(event.target.id) }

  boundHandleClick (event) { this.props.onClick(event.target.id) }

  boundInRenderHandleClick (event) { this.props.onClick(event.target.id) }

  unboundHandleClick (event) { this.props.onClick(event.target.id) }

  render () {
    return (
      <div>
        <button id='zero' onClick={(event) => { this.props.onClick(event.target.id) }} />
        <button id='one' onClick={arrowHandleClick} />
        <button id='two' onClick={boundHandleClick} />
        <button id='three' onClick={boundInRenderHandleClick.bind(this)} />
        <button id='four' onClick={unboundHandleClick} />
      </div>
    )
  }
}

При нажатии:

  • #zero будет правильно вызывать props.onClick. Проблема в том, что анонимная функция, созданная в методе рендеринга, будет воссоздавать при каждом рендеринге. Это плохо для производительности.

  • #one будет правильно вызывать props.onClick. Поскольку обратный вызов определяется как метод класса, он будет создан только тогда, когда MyComponent создается (и монтируется). Это приемлемый способ определения обратного вызова. Видимо медленнее, чем когда-то думали , но, на мой взгляд, он самый аккуратный.

  • #two правильно вызовет props.onClick. По сути, это то же самое, что arrowHandleClick, только это связанная функция в отличие от стрелочной функции. Для всех намерений и целей они одинаковы - , но обязательно копайтесь в различиях .

  • #three будет правильно вызывать props.onClick, и он имеет тот же результат, что и #two, но оказывает негативное влияние на производительность, как #zero - функции не должны создаваться или связываться в методе рендеринга.

  • #four не будет работать правильно и выдаст ошибку. При запуске this будет ссылаться на элемент (в данном случае #four), а не на экземпляр класса. Во всех других обработчиках this относится к экземпляру класса React, который имеет props.onClick.

Теперь есть новый общепринятый способ написания компонентов: использование простых функций и хуков. . this ушел в прошлое.

const MyComponent = (props) => {
  const handleClick = event => props.handleClick(event.target.id)

  const memoizedHandleClick = React.useCallback(
    event => props.handleClick(event.target.id), 
    [props.handleClick]
  )

  return (
    <div>
      <button id='zero' onClick={event => props.handleClick(event.target.id)} />
      <button id='one' onClick={handleClick} />
      <button id='two' onClick={memoizedHandleClick} />
    </div>
  )
}

Здесь все обратные вызовы работают правильно - с той лишь разницей, что memoizedHandleClick не будет воссоздаваться при каждом рендеринге, если props.handleClick не изменится. По моему собственному опыту, оба варианта приемлемы, и люди, похоже, больше не возражают против воссоздания обратных вызовов в функциональных компонентах, а скорее проявляют прагматичность c и решают проблемы с производительностью, когда вы с ними сталкиваетесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...