Я использую 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 раза. Почему так происходит?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Потому что не стоит сразу вызывать его в опоре 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()}
Лучшие практики и различные способы присоединения обработчиков событий можно найти на reactjs.org/docs/handling-events.html. Вы можете посмотреть, что может удовлетворить ваши потребности.