React: Prise en charge des écouteurs d'événements passifs

Créé le 7 avr. 2016  ·  62Commentaires  ·  Source: facebook/react

https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

Il serait bon que tout soit passif par défaut et que l'activation ne soit activée qu'en cas de besoin. Par exemple, vous pouvez écouter les événements de saisie de texte mais uniquement empêcher le comportement contrôlé par défaut ou utilisé lorsque vous avez des auditeurs actifs.

De même, nous pourrions unifier cela avec le modèle de threading de React Native. Par exemple, une chose que nous pourrions faire là-bas est de bloquer de manière synchrone le thread d'interface utilisateur lorsqu'il y a des écouteurs actifs, tels que la gestion des frappes.

cc @vjeux @ide

DOM React Core Team Big Picture Feature Request

Commentaire le plus utile

Je viens d'afficher un avertissement dans Chrome concernant la gestion de l'événement wheel, qui pourrait être optimisé s'il était enregistré en tant que gestionnaire d'événements passif. Donc, avoir cela dans React serait chouette !

Tous les 62 commentaires

Cela a atterri dans Chrome 51. Existe-t-il un plan mis à jour pour prendre en charge cela dans React ? :O

Comment est-ce possible si React n'a qu'un seul écouteur d'événement sur le document, puis délègue à d'autres ?
@sebmarkbage

Quel est l'état actuel du problème avec les événements passifs ?

Je viens d'afficher un avertissement dans Chrome concernant la gestion de l'événement wheel, qui pourrait être optimisé s'il était enregistré en tant que gestionnaire d'événements passif. Donc, avoir cela dans React serait chouette !

Vous voudrez également gérer des options arbitraires, telles que once qui a déjà atterri dans Firefox tous les soirs : https://twitter.com/mozhacks/status/758763803991474176. Liste complète : https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

FWIW, Facebook écoute les événements de roue actifs pour bloquer le défilement extérieur lorsque les barres latérales ou les fenêtres de discussion défilent. Nous ne pouvons pas implémenter l'interface utilisateur sans elle. Nous voulons toujours prendre en charge cette option, mais l'espace du problème est encore incomplet, il pourrait donc évoluer des solutions alternatives à ce problème qui n'impliquent pas d'écouteurs d'événements passifs. Il s'agit donc toujours d'un espace de conception actif.

Il est important de garder les deux auditeurs actifs et d'ajouter des auditeurs passifs.
Sur les applications de bureau, vous ne voyez aucune différence, mais sur les applications mobiles, les écouteurs de défilement passifs donnent une grande accélération de la vitesse.

Petite suggestion :

<SomeElement
  onScroll={this.onScrollThatCallsPreventDefault}
  onScrollPassive={this.onScrollThatJustListens}
  ...this.props
/>

@romulof ouais, c'est ainsi que vous enregistrez également des événements sur la phase de capture

<SomeElement
  onClick={this.onClick}
  onClickCapture={this.onClickCapture}
  onScrollPassive={this.onScrollPassive}
/>

donc j'imagine que ce serait l'API appropriée pour prendre en charge également les événements passifs.

Remarque : une question délicate est : comment enregistreriez-vous des événements passifs pour la phase de capture ? Je suppose que ce n'est pas possible, de par la nature des événements passifs. Puisqu'ils ne sont même pas autorisés à appeler event.preventDefault() , ce n'est donc probablement pas un problème.

@radubrehar , onScrollCapturePassive ressemble à toute la bible dans un étui à chameau.

:) Ce n'est pas le cas, puisqu'il n'y a pas d'événements passifs sur la phase de capture.

Bien sûr, cela n'a pas de sens, mais je ne compterais pas là-dessus. Il existe également d'autres types de liaison d'événements, tels que once .

Autre proposition :

<SomeElement
  onScroll={this.onScrollThatCallsPreventDefault}
/>
<SomePassiveElement
  onScroll={{
    passive: true,
    capture: true,
    handler: this.onScrollThatJustListens,
  }}
/>

De cette façon, React devrait détecter si le gestionnaire d'événements est une fonction (liaison normale) ou un objet contenant des options de liaison et la fonction de gestionnaire.

Je pense que l'approche objet avec des options est plus logique que onFooPassive , car d'autres options pourraient être nécessaires. Si combiné avec la suggestion de @sebmarkbage selon laquelle les événements devraient être passifs par défaut, cela ne serait probablement pas trop lourd.

Une autre approche qui me vient à l'esprit serait d'attacher des propriétés au gestionnaire d'événements pour leur permettre de se retirer du mode passif (ou de basculer d'autres options). Quelque chose comme ça:

class Foo extends React.Component {
  constructor() {
    this.handleScroll = this.handleScroll.bind(this);
    this.handleScroll.passive = false;
  }

  handleScroll() {
    ...
  }

  render() {
    return <div onScroll={this.handleScroll} />;
  }
}

En théorie, cela fonctionnerait plutôt bien avec les décorateurs, une fois qu'ils atterriraient.

En y réfléchissant un peu plus, je pense qu'il serait préférable d'ajouter une propriété d'options d'événement à la fonction, au lieu d'options individuelles. Cela permettrait à React de n'avoir à se soucier que d'une propriété au lieu de potentiellement plusieurs. Donc, pour ajuster mon exemple ci-dessus :

class Foo extends React.Component {
  constructor() {
    this.handleScroll = this.handleScroll.bind(this);
    this.handleScroll.options = { passive: false };
  }

  handleScroll() {
    ...
  }

  render() {
    return <div onScroll={this.handleScroll} />;
  }
}

Une autre pensée qui m'est venue est de savoir à quoi cela pourrait ressembler si nous modifiions la syntaxe JSX de manière à permettre la transmission de ces options via le JSX. Voici un exemple aléatoire auquel je n'ai pas beaucoup réfléchi :

return <div onScroll={this.handleScroll, { passive: false }} />;

J'ai également réfléchi à la question de savoir si les événements devraient être passifs par défaut ou non, et je suis un peu sur la clôture. D'une part, ce serait certainement bien pour des événements tels que les gestionnaires de défilement, mais je crains que cela ne provoque trop de turbulences et un comportement inattendu pour de nombreux gestionnaires de clics. Nous pourrions faire en sorte que certains événements soient passifs par défaut et d'autres non, mais cela finirait probablement par être déroutant pour les gens, donc ce n'est probablement pas une bonne idée.

Cette méthode est assez similaire à ce que j'ai proposé précédemment, sans modifier la syntaxe JSX.

return <div onScroll={{ handler: this.handleScroll, passive: true }} />;

Et la documentation serait simple :

div.propTypes = {
  ...
  onScroll: React.PropTypes.oneOf([
    React.PropTypes.func,
    React.PropTypes.shape({
      handler: React.PropTypes.func.isRequired,
      capture: React.PropTypes.bool,
      passive: React.PropTypes.bool,
      once: React.PropTypes.bool,
    }),
};

Les événements de réaction sont-ils passifs par défaut ? Il semble que ce soit ainsi pour les événements tactiles, au moins. Je ne peux pas preventDefault moins que je ne revienne aux écouteurs d'événements de niveau document vanilla.

@joshjg Les gestionnaires React reçoivent des "événements synthétiques", qui sont en quelque sorte comme des événements natifs, mais différents. Soit dit en passant, quelqu'un avec plus de connaissances devrait corriger ce que je suis sur le point de dire parce que je n'ai pas lu le code qui fait cela.

Je ne connais pas très bien les détails de l'implémentation, mais je sais que preventDefault fonctionne au moins _tant que les gestionnaires que vous empêchez sont également des gestionnaires d'événements React_. C'est mon expérience en tout cas.

Avec stopPropagation vous avez plus de chances de ne pas avoir de chance (par exemple, vous avez un écouteur de clics document qui ne peut pas être lié à React, et vous voulez éviter de bouillonner si vous cliquez à l'intérieur un certain élément). Dans ce cas, vous pouvez utiliser :

function stopPropagation (e) {
  e.stopPropagation();
  e.nativeEvent.stopImmediatePropagation();
}

[[MDN](https://developer.mozilla.org/en-US/docs/Web/API/Event/stopImmediatePropagation)]

Cela s'est légèrement éloigné du sujet principal, mais la réponse courte est que React n'utilise pas d'événements passifs, ils sont juste parfois traités dans un ordre étrange.

@joshjg @benwiley4000 @gaearon Récemment, l'équipe Chrome a changé son approche des événements tactiles au niveau du document, les rendant passifs par défaut. Et puisque React attache des événements au niveau du document, vous obtenez ce nouveau comportement.

Voir https://www.chromestatus.com/features/5093566007214080

Cela a indirectement modifié le comportement de React - je suppose que React ne mentionne pas explicitement passive: false lors de l'association d'événements - d'où le changement de comportement.

Je viens de le frapper aussi - vous devez donc enregistrer les événements tactiles à la main, avec addEventListener

Notez que l'intervention passive par défaut de Chrome ne s'applique qu'à touchstart et touchmove , pas wheel . Ainsi, un événement wheel sans {passive: true} explicite forcera toujours le défilement synchrone, pour la molette de la souris et le défilement du trackpad à deux doigts. (J'ai écrit un article de blog sur certaines des subtilités ici.)

De plus, nous (l'équipe Edge) n'avons pas l'intention de mettre en œuvre la même intervention, donc lorsque nous expédions des écouteurs d'événement passifs, vous voudrez toujours spécifier explicitement {passive: true} .

Pour info, j'ai commencé à descendre le passif: false path pour empêcher le corps de défiler sur mobile lorsqu'il y a un div de défilement, mais c'est un peu lourd d'utiliser preventDefault() pour bloquer le défilement. Je pourrais ajouter et supprimer le gestionnaire selon si le div est présent, ou revenir à une approche body.height = 100%. Le correctif body.height semble un peu bidon, mais alors je n'aurais pas besoin de passif: faux du tout.

Mon cas d'utilisation est que j'aimerais utiliser la méthode event.preventDefault() pour empêcher le défilement du conteneur lorsque l'utilisateur fait glisser un élément à l'intérieur.

Pour cela, je dois enregistrer l'écouteur d'événement comme non passif (passif : faux).
Comme les navigateurs passent au passif : vrai par défaut, j'aimerais pouvoir faire l'inverse

Malheureusement, je ne peux pas utiliser le style touch-action: none; car il est appliqué après le démarrage du toucher et c'est probablement pourquoi il n'a aucun effet.

Cela va en effet être un problème très bientôt, je suis surpris qu'en deux ans aucune solution n'ait été trouvée. Et la création manuelle d'écouteurs d'événements est un anti-modèle dans React.

Et si cela crée des changements décisifs, qu'il en soit ainsi. Il me manque peut-être une partie de l'histoire.

J'aime la nouvelle signature d'écouteur d'événement proposée par @romulof dans https://github.com/facebook/react/issues/6436#issuecomment -254331351.
Outre la résolution du problème décrit ici, il serait possible de spécifier d'autres EventListenerOptions telles que once

Je viens de tomber sur ce problème. J'ai un canevas où l'utilisateur peut dessiner. Lorsque vous dessinez sur Android, il va parfois « tirer pour rafraîchir » au lieu de faire un trait de peinture. Cela montre qu'il s'agit d'un problème réel. J'éviterai onTouch{Start,Move,End} pour le moment et utiliserai manuellement addEventListener comme solution de contournement.

J'aime beaucoup l'approche suggérée par @romulof . Il semble que cette solution ne nécessite pas non plus de changements de rupture.

@bobvanderlinden L'ajout de touch-action: none; à votre style de toile devrait fonctionner pour vous, cela brille vraiment pour ce cas d'utilisation. Les autres valeurs possibles peuvent également être très pratiques.

Cependant, comme l'a souligné @piotr-cz, touch-action ne résout pas universellement ce problème d'événements passifs dans son ensemble. Je rencontre également le même problème d'empêcher un conteneur de défiler tout en faisant glisser un élément enfant. Toutes les solutions de contournement sont assez difficiles et ajoutent une dette technique.

Malheureusement, la présence d'un écouteur non passif peut provoquer un jank important, même s'il n'y a pas de gestionnaire d'espace utilisateur réellement connecté. Chrome vous en parlera aux niveaux de journal verbose : [Violation] Handling of 'wheel' input event was delayed for 194 ms due to main thread being busy. Consider marking event handler as 'passive' to make the page more responsive. (il s'agit du gestionnaire de niveau supérieur ajouté par https://github.com/facebook/react/blob/92b7b172cce9958b846844f0b46fd7bbd8c5140d/packages/ react-dom/src/events/ReactDOMEventListener.js#L155)

@romulof @lencioni @radubrehar Êtes-vous conscient du fait que le drapeau passif n'est pas destiné à être utilisé sur les écouteurs d'événement de défilement ? Il doit être utilisé sur des événements comme touchmove etc. pour ne pas interférer avec les performances de défilement du navigateur. Vos exemples sont très déroutants pour moi.

Le réglage passif n'est pas important pour l'événement de défilement de base, car il ne peut pas être annulé, donc son écouteur ne peut de toute façon pas bloquer le rendu de la page.

Source : https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners

Informations supplémentaires : https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

Oui, j'en suis conscient maintenant. J'ai été mal informé quand j'ai écrit mon plus tôt
commentaires. Merci de clarifier!

Le mercredi 6 décembre 2017, 08h25 Martin Hofmann [email protected]
a écrit:

@romulof https://github.com/romulof @lencioni
https://github.com/lencioni @radubrehar https://github.com/radubrehar
Êtes-vous conscient du fait que le drapeau passif n'est pas destiné à être utilisé sur
faire défiler les écouteurs d'événement ? Il devrait être utilisé sur des événements comme touchmove, etc.
pour ne pas interférer avec les performances de défilement du navigateur. Vos exemples
sont très déroutants pour moi.

Le réglage passif n'est pas important pour l'événement de défilement de base, car il ne peut pas
être annulée, donc son écouteur ne peut pas bloquer le rendu de la page de toute façon.

La source:
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#Improving_scrolling_performance_with_passive_listeners

Information additionnelle:
https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md

-
Vous recevez ceci parce que vous avez été mentionné.

Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/facebook/react/issues/6436#issuecomment-349691618 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/AAL7zgbNCpHNui-TX7r2FYdhVxZfdBX8ks5s9r_4gaJpZM4ICWsW
.

@el-moalo-loco, je suis presque sûr d'avoir lu de la documentation sur le site de Google Developers sur l'utilisation d'écouteurs passifs pour les événements de défilement afin d'améliorer les performances. J'ai dû mal lire ou quelque chose a changé en cours de route. En tout cas merci beaucoup pour les éclaircissements !

@romulof @lencioni @el-moalo-loco https://developers.google.com/web/tools/lighthouse/audits/passive-event-listeners
Les auditeurs de roue devraient toujours être passifs même si les auditeurs de défilement n'ont pas à l'être. Je pense que cela peut être source de confusion.

@sebmarkbage Qu'en pensez-vous ? Ce support d'écouteur d'événement passif fera-t-il son chemin dans React un jour ?

Salut,

Je devais juste ajouter un écouteur d'événement actif dans componentDidMount comme ceci :

global.addEventListener("touchstart", this.touchStart(), { passive: false })

pour que je puisse appeler e.preventDefault() pour arrêter le défilement par défaut de Chrome et déplacer un élément dans touchStart() .

Afin de savoir quel élément je dois déplacer, j'ai dû ajouter onTouchStart à l'élément JSX comme ceci :

onTouchStart={this.touchStartSetElement(element)}

Dans touchStartSetElement() j'ai défini une propriété d'état element que je peux lire dans touchStart()

Si React prenait en charge les écouteurs d'événements actifs, cela se résumerait à une ligne.

Merci,

Philippe

PS : si vous essayez d'appeler e.preventDefault() dans un écouteur d'événement passif, vous obtenez cette erreur dans Chrome 56 :

[Intervention] Impossible d'empêcher la valeur par défaut dans l'écouteur d'événement passif car la cible est traitée comme passive. Voir https://www.chromestatus.com/features/5093566007214080

Les événements passifs sont devenus par défaut avec Chrome 56 par une " intervention " de Google et cassant le web en quelque sorte - mais aussi rendant le défilement plus rapide.

Cela devient de plus en plus un problème puisque Safari à partir d'iOS 11.3 est également passif par défaut, et la solution de contournement classique de touch-action:none n'y est pas prise en charge .

J'ai proposé une RFC https://github.com/reactjs/rfcs/pull/28 qui permettrait de créer des gestionnaires de références personnalisés qui fonctionnent comme des accessoires (c'est-à-dire que vous utilisez des propriétés comme vous le feriez onClick mais utilisez à la place calculé syntaxe de la propriété et le gestionnaire obtient les informations et les mises à jour de la valeur ref et prop). Ceux-ci peuvent être utilisés pour créer des bibliothèques pour à peu près tous les cas d'utilisation avancés que vous avez.

  • Les événements passifs, explicitement non passifs, uniques et de capture sont tous faciles à faire avec.
  • Des choses encore plus avancées que la simple inscription d'un gestionnaire d'événements peuvent être faites avec eux.
  • Du point de vue de l'utilisateur, ils sont simples à utiliser, il suffit de transmettre ce que la bibliothèque vous donne en tant que propriété calculée à n'importe quel élément. par exemple import {onScroll} from 'react-passive-events'; <div [onScroll]={scrollHandler} />

Je ne pense pas que cela devrait être le moyen d'enregistrer tous les événements.

Cependant, au lieu de proposer des moyens complexes pour gérer l'enregistrement de tous les types d'événements possibles (capture, passif, etc...), je recommande de décider quel devrait être le comportement par défaut pour la plupart des événements (passifs ou non passifs) et d'utiliser ces enregistrements props pour gérer des cas d'utilisation plus avancés.

Tous les événements tactiles sont désormais passifs par défaut dans iOS 11.3. Ainsi, appeler event.preventDefault() dans n'importe quel gestionnaire d'événement tactile est désormais non efficace 😢

https://codesandbox.io/s/l4kpy569ol

Sans pouvoir forcer les gestionnaires d'événements non passifs, nous avons du mal à contourner les changements iOS 11.3 https://github.com/atlassian/react-beautiful-dnd/issues/413

Je suis venu voir comment Vue.js gérait cela, et j'aime bien leur approche :

<!-- the click event's propagation will be stopped -->
<a v-on:click.stop="doThis"></a>

<!-- the submit event will no longer reload the page -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- modifiers can be chained -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- just the modifier -->
<form v-on:submit.prevent></form>

Il y a cette liste de modificateurs :

  • .arrêter
  • .empêcher
  • .Capturer
  • .soi
  • .une fois que
  • .passif

Et vous pouvez composer des événements comme vous le souhaitez. Peut-être que cela peut aider comme source d'inspiration pour ce problème.

@KeitIG Je travaille sur un fork de Vue-loader conçu pour React

https://github.com/stalniy/react-webpack-loader

Cela me rend triste

selection_028

Je ne sais pas si cela est déjà suggéré - ou si cela a du sens pour quelqu'un d'autre que moi, cependant :

onTouchStart={listener} 

à

onTouchStart={listener, options}

feraient tous deux passer des options telles que { passive, true, once: true } un moyen naturel de le faire, et cela correspondrait également au schéma addEventListener .

Passer à la suggestion de @phaistonian supprimerait le besoin de l'un des gestionnaires onEventNameCapture qui existent aujourd'hui

@alexreardon Je pense vraiment que ce n'est pas une option, car dans plain js, listener, options est une expression, qui vaut options , donc la construction ci-dessus n'est pas ce que vous voulez dire. Cela nécessiterait de changer la façon dont jsx compile en js et serait un changement décisif. Je doute que l'équipe de réaction suive cette voie.

Des avis?

S'agissant d'une expression, cela pourrait être fait différemment avec la même intention.

Il y a probablement beaucoup d'options. Les options incluent :

import {handler} from 'React';

onTouchStart={handler(listener, options)}
onTouchStart={{listener, options}}

ou

onTouchStart={[listener, options]}

ou

onTouchStart={listener} onTouchStartOptions={options}

J'aime le plus l'idée de passer un objet. Quoi qu'il en soit, cela nécessite une solution.

y a-t-il une solution maintenant?

y a-t-il une solution maintenant?

Votre classique addEventListener et removeEventListener en componentDidMount et componentWillUnmount respectivement.

Ouais, ça craint.

Et à quoi pensez-vous pour le résoudre à l'aide d'un crochet ?

...
const onClickPassive = useEventListener((e) => {
 console.log('passive event')
}, { passive: true })

return (
  <button onClick={onClickPassive}>Click me</button>
)

@ara4n utiliser le crochet est bien, mais il faut encore une solution classique pour la réaction sans crochet

@sebmarkbage des mises à jour à ce sujet ? Chrome vient de l'expédier et a cassé notre application.

https://www.chromestatus.com/features/6662647093133312

[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See https://www.chromestatus.com/features/6662647093133312
Cela se reproduit lorsque j'ai essayé de bloquer le comportement de défilement par défaut dans l'écouteur d'événements onWheel

@kychanbi Idem pour moi, mais je ne rencontre cette erreur que sur Windows Chrome.

@kychanbi Oh, c'est une fonctionnalité de Chrome 73 qui traite les écouteurs d'événement Wheel/Mousewheel au niveau du document comme passifs

Vous pouvez utiliser la propriété css sur l'action tactile div de votre conteneur de composants : aucune

.récipient {
action tactile : aucune ;
}

@madcher, il semble que cela ne fonctionne pas pour les événements de souris.
Je l'ai finalement résolu en utilisant javascript natif
element.addEventListener("wheel", eventHandler);

Un petit extrait pour aider ceux qui sont confrontés à ce problème :

import React, { useRef, useEffect } from 'react'

const BlockPageScroll = ({ children }) => {
  const scrollRef = useRef(null)
  useEffect(() => {
    const scrollEl = scrollRef.current
    scrollEl.addEventListener('wheel', stopScroll)
    return () => scrollEl.removeEventListener('wheel', stopScroll)
  }, [])
  const stopScroll = e => e.preventDefault()
  return (
    <div ref={scrollRef}>
      {children}
    </div>
  )
}

const Main = () => (
  <BlockPageScroll>
    <div>Scrolling here will only be targeted to inner elements</div>
  </BlockPageScroll>
)

@fou

D' onWheel manière ou d' onWheel ne fonctionnent pas avec les css touch-action: none;

    componentRef = React.createRef(null);
    handleWheel = (e) => {
      e.preventDefault();
    }
    render() {
      <Container style={{ touchAction: 'none' }} onWheel={this.handleWheel}>
        ...
      </Container>
    }

toujours cette erreur :
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL>

Version de travail

alternative à la solution de crochets de @markpradhan , si vous utilisez toujours un composant à l'ancienne, vous pouvez le faire :

    componentRef = React.createRef();
    handleWheel = (e) => {
      e.preventDefault();
    }
    componentDidMount() {
      if (this.componentRef.current) {
        this.componentRef.current.addEventListener('wheel', this.handleWheel);
      }
    }
    componentWillUnmount() {
      if (this.componentRef.current) {
        this.componentRef.current.removeEventListener('wheel', this.handleWheel);
      }
    }
    render() {
      <Container ref={this.componentRef}>...</Container>
    }

@Fonger Probablement à cause du # 14856

Quelque chose comme cela a été suggéré, mais voici quelques autres idées.

function MyComponent() {
  function onScroll(event) { /* ... */ }
  onScroll.options = {capture, passive, ...};
  return <div onScroll={onScroll} />;
}

Celui-ci vous permettrait d'opter facilement pour des événements passifs ou de capturer des événements sans avoir besoin d'un changement de rupture. Cependant, j'ai été intrigué par l'idée d'un écouteur d'événement passif par défaut. Je me souviens que preventDefault était un obstacle majeur (parmi d'autres) qui empêche React de s'exécuter dans un worker.

js function MyComponent() { function onScroll(event) { /* ... */ } onScroll.shouldPreventDefault = (event): boolean => { // some logic to decide if preventDefault() should be called. } onScroll.shouldStopPropagation = (event): boolean => { // some logic to decide if stopPropagation() should be called. } return <div onScroll={onScroll} />; }
Il serait difficile de garantir que cela ne devienne pas un changement décisif, mais si cela était appliqué, tout le code pour décider si un événement doit être preventDefault ed serait isolé dans le code et React serait capable de exécutez uniquement cette partie sur le thread principal et exécutez tout le reste dans un programme de travail séparé ou de manière asynchrone.

Jusqu'à ce que cela soit résolu, je pense qu'il serait préférable que les références à event.preventDefault() soient supprimées de la documentation ou soient au moins marquées d'un avertissement concernant l'incapacité de Chrome à preventDefault sur les événements passifs.

Je m'interroge sur les implications du changement de la délégation d'événement de React v17. Lighthouse a une règle https://web.dev/uses-passive-event-listeners/ qui teste les événements non passifs.

Auparavant, <div onTouchStart /> était enregistré sur le document, qui est passif par défaut . Cependant, avec React v17, l'événement est enregistré à la racine de l'arbre React, qui n'est plus passif sans le demander spécifiquement.

Reproduction : https://codesandbox.io/s/material-demo-forked-e2u72?file=/demo.js , en direct : https://csb-e2u72.netlify.app/

Capture d’écran 2020-08-19 à 16 11 31

Oui. Semble préoccupant. Je vais déposer un nouveau problème.

Classé https://github.com/facebook/react/issues/19651 pour la discussion React 17.

Cette page vous a été utile?
0 / 5 - 0 notes