twitter-bootstrap 基于滚动 React JS 的切换类
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44612364/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Toggle Class based on scroll React JS
提问by Fernando B
I'm using bootstrap 4 nav bar and would like to change the background color after ig 400px down scroll down. I was looking at the react docs and found a onScroll but couldn't find that much info on it. So far I have...
我正在使用 bootstrap 4 导航栏,并想在 ig 400px 向下滚动后更改背景颜色。我正在查看 react 文档并找到了一个 onScroll 但找不到关于它的太多信息。到目前为止我有...
I don't know if I'm using the right event listener or how to set the height etc.
我不知道我是否使用了正确的事件侦听器或如何设置高度等。
And I'm not really setting inline styles...
而且我并没有真正设置内联样式...
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;
回答by glennreyes
One way to add a scroll listener is to use the componentDidMount()lifecycle method. Following example should give you an idea:
添加滚动侦听器的componentDidMount()一种方法是使用生命周期方法。下面的例子应该给你一个想法:
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'));
This changes the Text from "Scroll down" to "Scroll up" when your scrollY position is at 100 and above.
当您的 scrollY 位置在 100 及以上时,这会将文本从“向下滚动”更改为“向上滚动”。
Edit: Should avoid the overkill of updating the state on each scroll. Only update it when the boolean value changes.
编辑:应该避免在每个滚动上更新状态的矫枉过正。仅在布尔值更改时更新它。
回答by Pouya Ataei
For those of you who are reading this question in 2019, I've taken @glennreyes answer and rewritten it using React Hooks:
对于那些在 2019 年阅读这个问题的人,我已经回答了@glennreyes 并使用React Hooks重写了它:
const [scroll, setScroll] = useState(0)
useEffect(() => {
document.addEventListener("scroll", () => {
const scrollCheck = window.scrollY < 100
if (scrollCheck !== scroll) {
setScroll(scrollCheck)
}
})
})
Bear in mind that, useStatehas an array of two elements, firstly the state objectand secondly the function that updates it.
请记住,useState有一个包含两个元素的数组,首先是状态对象,其次是更新它的函数。
Along the lines, useEffecthelps us replace componentDidmount, the function written currently does not do any clean ups as it's not necessary in this case.
沿着这条线,useEffect帮助我们替换componentDidmount,当前编写的函数不做任何清理,因为在这种情况下没有必要。
If you find it essential to clean up, you can just return a function inside the useEffect.
如果您发现清理很重要,您可以在useEffect 中返回一个函数。
You can read comprehensively here.
您可以在此处全面阅读。
UPDATE:
更新:
If you guys felt like making it modularand even do the clean up, you can do something like this:
如果你们想把它模块化,甚至做清理,你可以做这样的事情:
Create a custom hookas below;
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 }Call it inside any componentthat you find suitable:
const component = () => { // calling our custom hook const scroll = useScrollHandler() ....... rest of your code }
创建一个自定义钩子,如下所示;
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 }在您认为合适的任何组件中调用它:
const component = () => { // calling our custom hook const scroll = useScrollHandler() ....... rest of your code }
回答by amirhossein693
It's Better
更好
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'));
回答by Sergiu Dogotaru
This is yet another take / my take on hooksapproach for on scroll displaying and hiding of a random page element.
这是用于滚动显示和隐藏随机页面元素的另一种方法/我对钩子方法的看法。
I have been very much inspired from: Dan Abramov's post here.
我的灵感来自:丹·阿布拉莫夫( Dan Abramov) 的帖子。
You can check a full working example, in this CodeSandbox demo.
您可以在此CodeSandbox 演示中查看完整的工作示例。
The following is the code for the useScroll custom hook:
下面是 useScroll 自定义钩子的代码:
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);
});
};
And this hook will be consumed like this:
这个钩子会像这样被消耗:
useScroll(direction => {
setScrollDirection(direction);
});
A full component using this custom hook:
使用此自定义钩子的完整组件:
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);
And lastly the code for CustomElement:
最后是 CustomElement 的代码:
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>
);
};
回答by wildair
I have changed @PouyaAtaei answer a bit for my use case.
我已经为我的用例更改了@PouyaAtaei 的答案。
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
}
};
Calling the hook:
调用钩子:
Const component = () => {
// calling our custom hook and optional distance agument.
const scroll = useHasScrolled(250)
}

