J'ai construit un composant dans React qui est censé mettre à jour son propre style sur le défilement de la fenêtre pour créer un effet de parallaxe.
La render
méthode du composant ressemble à ceci:
function() {
let style = { transform: 'translateY(0px)' };
window.addEventListener('scroll', (event) => {
let scrollTop = event.srcElement.body.scrollTop,
itemTranslate = Math.min(0, scrollTop/3 - 60);
style.transform = 'translateY(' + itemTranslate + 'px)');
});
return (
<div style={style}></div>
);
}
Cela ne fonctionne pas car React ne sait pas que le composant a changé, et par conséquent, le composant n'est pas rendu.
J'ai essayé de stocker la valeur de itemTranslate
dans l'état du composant et d'appelersetState
le rappel de défilement. Cependant, cela rend le défilement inutilisable car il est terriblement lent.
Une suggestion sur la façon de procéder?
javascript
reactjs
Alejandro Pérez
la source
la source
render
dans le même thread) ne devraient être concernées que par la logique relative au rendu / mise à jour du DOM réel dans React. Au lieu de cela, comme indiqué par @AustinGreco ci-dessous, vous devez utiliser les méthodes de cycle de vie React données pour créer et supprimer votre liaison d'événement. Cela le rend autonome à l'intérieur du composant et garantit l'absence de fuite en s'assurant que la liaison d'événement est supprimée si / lorsque le composant qui l'utilise est démonté.Réponses:
Vous devez lier l'auditeur
componentDidMount
, de cette façon, il n'est créé qu'une seule fois. Vous devriez pouvoir stocker le style dans l'état, l'auditeur était probablement la cause de problèmes de performances.Quelque chose comme ça:
la source
this.handleScroll = this.handleScroll.bind(this)
le liera à l'intérieurhandleScroll
au composant, au lieu de window.event.target.scrollingElement.scrollTop
Vous pouvez passer une fonction à l'
onScroll
événement sur l'élément React: https://facebook.github.io/react/docs/events.html#ui-eventsUne autre réponse similaire: https://stackoverflow.com/a/36207913/1255973
la source
Ma solution pour faire une barre de navigation responsive (position: 'relative' quand on ne défile pas et fixe lors du défilement et non en haut de la page)
Aucun problème de performance pour moi.
la source
pour aider tous ceux qui ont remarqué les problèmes de comportement / performances lents lors de l'utilisation de la réponse Austins, et qui veulent un exemple utilisant les références mentionnées dans les commentaires, voici un exemple que j'utilisais pour faire basculer une classe pour une icône de défilement haut / bas:
Dans la méthode de rendu:
Dans la méthode du gestionnaire:
Et ajoutez / supprimez vos gestionnaires de la même manière qu'Austin l'a mentionné:
docs sur les réf .
la source
this.scrollIcon.className = whatever-you-want
.className
ouclassList
. De plus, je n'en avais pas besoinwindow.addEventListener()
: je viens d'utiliser React'sonScroll
, et c'est aussi rapide, tant que vous ne mettez pas à jour les props / state!J'ai trouvé que je ne peux pas ajouter avec succès l'écouteur d'événements à moins que je passe true comme ceci:
la source
userCapture
: facultatif. Valeur booléenne qui spécifie si l'événement doit être exécuté dans la capture ou dans la phase de bullage. Valeurs possibles: true - Le gestionnaire d'événements est exécuté dans la phase de capture false - Par défaut. Le gestionnaire d'événements est exécuté dans la phase de bouillonnementUn exemple utilisant classNames , les hooks React useEffect , useState et styled-jsx :
la source
avec crochets
la source
Exemple de composant de fonction utilisant useEffect:
Remarque : vous devez supprimer l'écouteur d'événements en renvoyant une fonction de «nettoyage» dans useEffect. Sinon, à chaque mise à jour du composant, vous aurez un écouteur de défilement de fenêtre supplémentaire.
la source
Si ce qui vous intéresse est un composant enfant qui défile, cet exemple peut être utile: https://codepen.io/JohnReynolds57/pen/NLNOyO?editors=0011
la source
J'ai résolu le problème en utilisant et en modifiant les variables CSS. De cette façon, je n'ai pas à modifier l'état du composant, ce qui cause des problèmes de performances.
index.css
Navbar.jsx
Navbar.module.css
la source
Mon pari ici est d'utiliser des composants Function avec de nouveaux crochets pour le résoudre, mais au lieu d'utiliser
useEffect
comme dans les réponses précédentes, je pense que la bonne option seraituseLayoutEffect
pour une raison importante:Cela peut être trouvé dans la documentation React . Si nous utilisons à la
useEffect
place et que nous rechargeons la page déjà défilée, le défilement sera faux et notre classe ne sera pas appliquée, provoquant un comportement indésirable.Un exemple:
Une solution possible au problème pourrait être https://codepen.io/dcalderon/pen/mdJzOYq
la source
useLayoutEffect
. J'essaie de voir ce que vous avez mentionné.useEffect
ici par rapport àuseLayoutEffect
..Header--scrolled
parfois une classe, mais 100%.Header--scrolledLayout
est appliqué correctement grâce à useLayoutEffect.Voici un autre exemple en utilisant CROCHET fontAwesomeIcon et Kendo UI React
[! [Capture d' écran ici] [1]] [1]
la source
Mise à jour pour une réponse avec React Hooks
Ce sont deux crochets - un pour la direction (haut / bas / aucun) et un pour la position réelle
Utilisez comme ceci:
Voici les crochets:
la source
Pour développer la réponse de @ Austin, vous devez ajouter
this.handleScroll = this.handleScroll.bind(this)
à votre constructeur:Cela donne
handleScroll()
accès à la portée appropriée lorsqu'il est appelé à partir de l'écouteur d'événements.Il faut aussi savoir que vous ne pouvez pas faire la
.bind(this)
dans lesaddEventListener
ouremoveEventListener
méthodes , car ils chacun des références de retour à différentes fonctions et l'événement ne seront pas supprimés lorsque le composant démontages.la source