Voici un composant de base. <ul>
et <li>
ont tous deux des fonctions onClick. Je veux seulement que l'onClick sur le <li>
se déclenche, pas le <ul>
. Comment puis-je atteindre cet objectif?
J'ai joué avec e.preventDefault (), e.stopPropagation (), en vain.
class List extends React.Component {
constructor(props) {
super(props);
}
handleClick() {
// do something
}
render() {
return (
<ul
onClick={(e) => {
console.log('parent');
this.handleClick();
}}
>
<li
onClick={(e) => {
console.log('child');
// prevent default? prevent propagation?
this.handleClick();
}}
>
</li>
</ul>
)
}
}
// => parent
// => child
J'ai eu le même problème. J'ai trouvé stopPropagation did work. Je scinderais l'élément de la liste en un composant séparé, comme suit:
class List extends React.Component {
handleClick = e => {
// do something
}
render() {
return (
<ul onClick={this.handleClick}>
<ListItem onClick={this.handleClick}>Item</ListItem>
</ul>
)
}
}
class ListItem extends React.Component {
handleClick = e => {
e.stopPropagation();
this.props.onClick();
}
render() {
return (
<li onClick={this.handleClick}>
{this.props.children}
</li>
)
}
}
React utilise la délégation d’événements avec un seul écouteur d’événements sur le document pour les événements masqués, comme «clic» dans cet exemple, ce qui signifie qu’arrêter la propagation n’est pas possible; l'événement réel s'est déjà propagé au moment où vous interagissez avec lui dans React. stopPropagation sur l'événement synthétique de React est possible car React gère la propagation d'événements synthétiques en interne.
stopPropagation: function(e){
e.stopPropagation();
e.nativeEvent.stopImmediatePropagation();
}
Ce n’est pas idéal à 100%, mais s’il est trop pénible de transmettre props
chez les enfants -> mode pour enfants ou créer un Context.Provider
/Context.Consumer
juste à cet effet), et vous avez affaire à une autre bibliothèque qui a son propre gestionnaire, elle tourne avant la vôtre, vous pouvez aussi essayer:
function myHandler(e) {
e.persist();
e.nativeEvent.stopImmediatePropagation();
e.stopPropagation();
}
D'après ce que j'ai compris, la méthode event.persist
empêche un objet d'être immédiatement renvoyé dans le pool SyntheticEvent
de React. Donc, à cause de cela, la event
passée dans React n’existe plus au moment où vous l’atteignez! Cela se produit chez les petits-enfants à cause de la manière dont React gère les choses en interne en vérifiant d'abord que le parent est en déshérence pour les gestionnaires SyntheticEvent
(surtout si le parent avait un rappel).
Tant que vous n'appelez pas persist
sur quelque chose qui créerait une mémoire importante pour continuer à créer des événements tels que onMouseMove
(et que vous ne créez pas une sorte de jeu Cookie Clicker comme celui de Grandma's Cookies), tout devrait bien se passer!
Remarquez également: en lisant de temps en temps autour de leur GitHub, nous devrions surveiller de près les versions futures de React car ils peuvent résoudre éventuellement une partie de la douleur liée à cela, car ils semblent vouloir créer du code React de pliage. un compilateur/transpiler.
La nouvelle façon de procéder est beaucoup plus simple et vous fera gagner du temps! Passez simplement l'événement dans le gestionnaire de clics d'origine et appelez preventDefault();
.
clickHandler(e){
e.preventDefault();
//Your functionality here
}
J'ai eu des problèmes à faire fonctionner event.stopPropagation()
. Si vous aussi, essayez de le placer en haut de votre fonction de gestionnaire de clics, c’est ce que je devais faire pour empêcher l’événement de se propager. Exemple de fonction:
toggleFilter(e) {
e.stopPropagation(); // If moved to the end of the function, will not work
let target = e.target;
let i = 10; // Sanity breaker
while(true) {
if (--i === 0) { return; }
if (target.classList.contains("filter")) {
target.classList.toggle("active");
break;
}
target = target.parentNode;
}
}
Vous pouvez éviter la propagation d'événements en vérifiant la cible de l'événement.
Par exemple, si une entrée est imbriquée dans l'élément div où vous avez le gestionnaire pour l'événement click, et que vous ne voulez pas la gérer, lorsque vous cliquez sur l'entrée, vous pouvez simplement passer event.target
dans votre handler et check is handler doivent être exécutés en fonction des propriétés de la cible.
Par exemple, vous pouvez vérifier if (target.localName === "input") { return}
.
C'est donc un moyen "d'éviter" l'exécution du gestionnaire