J'utilise bootstrap 4 barre de navigation et je voudrais changer la couleur d'arrière-plan après ig 400px bas défiler vers le bas. Je regardais les documents React et j'ai trouvé un onScroll mais je n'ai pas pu trouver grand-chose Jusqu'à présent, j'ai ...
Je ne sais pas si j'utilise le bon écouteur d'événement ou comment définir la hauteur, etc.
Et je ne mets pas vraiment de styles en ligne ...
import React, { Component } from 'react';
class App extends Component {
constructor(props) {
super(props);
this.state = { scrollBackground: 'nav-bg' };
this.handleScroll = this.handleScroll.bind(this);
}
handleScroll(){
this.setState ({
scrollBackground: !this.state.scrollBackground
})
}
render() {
const scrollBg = this.scrollBackground ? 'nav-bg scrolling' : 'nav-bg';
return (
<div>
<Navbar inverse toggleable className={this.state.scrollBackground}
onScroll={this.handleScroll}>
...
</Navbar>
</div>
);
}
}
export default App;
Une façon d'ajouter un écouteur de défilement consiste à utiliser la méthode de cycle de vie componentDidMount()
. L'exemple suivant devrait vous donner une idée:
import React from 'react';
import { render } from 'react-dom';
class App extends React.Component {
state = {
isTop: true,
};
componentDidMount() {
document.addEventListener('scroll', () => {
const isTop = window.scrollY < 100;
if (isTop !== this.state.isTop) {
this.setState({ isTop })
}
});
}
render() {
return (
<div style={{ height: '200vh' }}>
<h2 style={{ position: 'fixed', top: 0 }}>Scroll {this.state.isTop ? 'down' : 'up'}!</h2>
</div>
);
}
}
render(<App />, document.getElementById('root'));
Cela change le texte de "Défilement vers le bas" à "Défilement vers le haut" lorsque votre position scrollY est à 100 et au-dessus.
Modifier: devrait éviter l'excès de mise à jour de l'état sur chaque parchemin. Ne le mettez à jour que lorsque la valeur booléenne change.
Pour ceux d'entre vous qui ont lu cette question en 2019 , j'ai pris la réponse @glennreyes et l'ai réécrite en utilisant React Hooks :
const [scroll, setScroll] = useState(0)
useEffect(() => {
document.addEventListener("scroll", () => {
const scrollCheck = window.scrollY < 100
if (scrollCheck !== scroll) {
setScroll(scrollCheck)
}
})
})
Gardez à l'esprit que, useState a un tableau de deux éléments, tout d'abord l'objet d'état et d'autre part la fonction qui la met à jour .
Dans le même ordre d'idées, useEffect nous aide à remplacer componentDidmount , la fonction écrite actuellement ne fait aucun nettoyage car ce n'est pas nécessaire dans ce cas.
Si vous trouvez qu'il est essentiel de nettoyer, vous pouvez simplement retourner une fonction à l'intérieur de useEffect .
Vous pouvez lire en détail ici .
MISE À JOUR:
Si vous aviez envie de le rendre modulaire et même de faire le nettoyage , vous pouvez faire quelque chose comme ceci:
Créez un crochet personnalisé comme ci-dessous;
import { useState, useEffect } from "react"
export const useScrollHandler = () => {
// setting initial value to true
const [scroll, setScroll] = useState(1)
// running on mount
useEffect(() => {
const onScroll = () => {
const scrollCheck = window.scrollY < 10
if (scrollCheck !== scroll) {
setScroll(scrollCheck)
}
}
// setting the event handler from web API
document.addEventListener("scroll", onScroll)
// cleaning up from the web API
return () => {
document.removeEventListener("scroll", onScroll)
}
}, [scroll, setScroll])
return scroll
}
Appelez-le à l'intérieur de tout composant que vous trouvez:
Const component = () => {
// calling our custom hook
const scroll = useScrollHandler()
....... rest of your code
}
C'est mieux
import React from 'react';
import { render } from 'react-dom';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
isTop: true
};
this.onScroll = this.onScroll.bind(this);
}
componentDidMount() {
document.addEventListener('scroll', () => {
const isTop = window.scrollY < 100;
if (isTop !== this.state.isTop) {
this.onScroll(isTop);
}
});
}
onScroll(isTop) {
this.setState({ isTop });
}
render() {
return (
<div style={{ height: '200vh' }}>
<h2 style={{ position: 'fixed', top: 0 }}>Scroll {this.state.isTop ? 'down' : 'up'}!</h2>
</div>
);
}
}
render(<App />, document.getElementById('root'));
J'ai changé un peu la réponse @PouyaAtaei pour mon cas d'utilisation.
import { useState, useEffect } from "react"
// Added distance parameter to determine how much
// from the top tell return value is updated.
// The name of the hook better reflects intended use.
export const useHasScrolled = (distance = 10) => {
// setting initial value to false
const [scroll, setScroll] = useState(false)
// running on mount
useEffect(() => {
const onScroll = () => {
// Logic is false tell user reaches threshold, then true after.
const scrollCheck = window.scrollY >= distance;
if (scrollCheck !== scroll) {
setScroll(scrollCheck)
}
}
// setting the event handler from web API
document.addEventListener("scroll", onScroll)
// cleaning up from the web API
return () => {
document.removeEventListener("scroll", onScroll)
}
}, [scroll, setScroll])
return scroll
}
};
Appeler le crochet:
Const component = () => {
// calling our custom hook and optional distance agument.
const scroll = useHasScrolled(250)
}
Ceci est encore une autre approche de prise/ma prise sur crochets pour l'affichage sur le défilement et le masquage d'un élément de page aléatoire.
Je me suis beaucoup inspiré de: le post de Dan Abramov ici .
Vous pouvez consulter un exemple de travail complet, dans cette démo CodeSandbox .
import React, { useState, useEffect } from "react";
export const useScroll = callback => {
const [scrollDirection, setScrollDirection] = useState(true);
const handleScroll = () => {
const direction = (() => {
// if scroll is at top or at bottom return null,
// so that it would be possible to catch and enforce a special behaviour in such a case.
if (
window.pageYOffset === 0 ||
window.innerHeight + Math.ceil(window.pageYOffset) >=
document.body.offsetHeight
)
return null;
// otherwise return the direction of the scroll
return scrollDirection < window.pageYOffset ? "down" : "up";
})();
callback(direction);
setScrollDirection(window.pageYOffset);
};
// adding and cleanning up de event listener
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
});
};
useScroll(direction => {
setScrollDirection(direction);
});
import React, { useState } from "react";
import ReactDOM from "react-dom";
import CustomElement, { useScroll } from "./element";
import Scrollable from "./scrollable";
function Page() {
const [scrollDirection, setScrollDirection] = useState(null);
useScroll(direction => {
setScrollDirection(direction);
});
return (
<div>
{/* a custom element that implements some scroll direction behaviour */}
{/* "./element" exports useScroll hook and <CustomElement> */}
<CustomElement scrollDirection={scrollDirection} />
{/* just a lorem ipsum long text */}
<Scrollable />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<Page />, rootElement);
import React, { useState, useEffect } from "react";
export default props => {
const [elementVisible, setElementVisible] = useState(true);
const { scrollDirection } = props;
// when scroll direction changes element visibility adapts, but can do anything we want it to do
// U can use ScrollDirection and implement some page shake effect while scrolling
useEffect(() => {
setElementVisible(
scrollDirection === "down"
? false
: scrollDirection === "up"
? true
: true
);
}, [scrollDirection]);
return (
<div
style={{
background: "#ff0",
padding: "20px",
position: "fixed",
width: "100%",
display: `${elementVisible ? "inherit" : "none"}`
}}
>
element
</div>
);
};