Почему onClick срабатывает несколько раз

Я использую Semantic-ui-react, redux и react-router-dom. В моем компоненте у меня есть панель навигации:

<Menu >     
  <Menu.Item as = {Link} to = "/" onClick = {this.onNavBarItemCLick()}>
    home
  </Menu.Item>

  <Menu.Item as = {Link} to = "profile" onClick = {this.onNavBarItemCLick()}>
    profile
  </Menu.Item>

  <Menu.Item as = {Link} to = "shop" onClick = {this.onNavBarItemCLick()}>
    shop
  </Menu.Item>
</Menu>

Если я нажимаю на один из элементов навигации, метод onNavBarItemClick срабатывает 3 раза. Почему так происходит?

Лучшие практики и различные способы присоединения обработчиков событий можно найти на reactjs.org/docs/handling-events.html. Вы можете посмотреть, что может удовлетворить ваши потребности.

maazadeeb 04.04.2018 11:03
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
1
120
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Потому что не стоит сразу вызывать его в опоре onClick. использовать это

<Menu.Item as = {Link} to = "/" onClick = {this.onNavBarItemCLick}>

Что в итоге происходит, так это то, что onNavBarItemCLick вызывается каждый раз, когда вызывается функция рендеринга при изменении состояния.

Поскольку вы вызываете метод немедленно, вместо этого вы должны передать обработчик только атрибуту onClick:

as = {Link} to = "shop" onClick = {this.onNavBarItemCLick.bind(this)}>
Ответ принят как подходящий

Решение

Вам нужно заменить

onClick = {this.onNavBarItemCLick()}

с участием

onClick = {() => this.onNavBarItemCLick()}  // perserving class's this

или если вы предпочитаете обозначение привязки

onClick = {this.onNavBarItemCLick.bind(this)} // perserving class's this

еще

onClick = {this.onNavBarItemCLick} // not perserving class's this

Почему так происходит

Это происходит потому, что при нажатии снова вызывается render(). React очень эффективен при повторном рендеринге, так что это то, что должно происходить.

Проблема с вашей реализацией заключалась в том, что вместо передачи ссылки на метод вы передавали возвращаемое значение такого метода.

Опора onClick принимает функцию как значение, так в чем же здесь проблема?

<MyComponent onClick = {this.handleClick()} />

с помощью this.handleClick() мгновенно вызывает функцию и передает ее возвращаемое значение в onClick. Здесь вы хотите передать функцию onClick так:

<MyComponent onClick = {this.handleClick} />

Но вы, вероятно, получите еще одну ошибку, если this.handleClick использует this, поскольку он не привязан автоматически к классу React. Есть способы исправить это, например, привязать this в конструкторе, использовать функцию массива для handleClick или напрямую связать this при передаче функции в onClick, например

<MyComponent onClick = {this.handleClick.bind(this)} />

Пойдя немного дальше, вы также можете вернуть функцию в handleClick, которая здесь совершенно бесполезна. Это только для иллюстрации:

class MyComponent extends React.Component {
  handleClick () {
    return () => { console.info('I am triggered on click') }
  }

  render () {
    // We call this.handleClick() which returns the function
    // that'll be actually called on click.
    return <div onClick = {this.handleClick()} />
  }
}

надеюсь, это поможет

Когда вы выполняете this.onNavBarItemClick(), происходит то, что скобка выполняет функцию в этой точке. В то время как this.onNavBarItemClick будет рассматривать это как переменную.

Итак, в приведенном выше фрагменте кода, когда вы выполняете onClick = {this.onNavBarItemClick()}, функция вызывается там сама без нажатия пользователем на нее. Тогда как если вы выполните onClick = {this.onNavBarItemCLick}, функция будет вызвана, только если вы нажмете на нее.

Вы также можете сделать onClick = {()=>this.onNavBarItemClick()}. Делая это, вы создаете анонимную функцию и передаете ее onClick.

Таким образом, вы можете использовать либо onClick = {this.onNavBarItemClick}, либо onClick = {()=> this.onNavBarItemClick()}

Другие вопросы по теме