私はbootstrap 4ナビゲーションバーを使用しており、400ピクセルのダウンスクロールダウン後にバックグラウンドカラーを変更したいと考えています。反応ドキュメントを見ていて、onScrollを見つけましたが、それほど多くは見つかりませんでした。これに関する情報これまでのところ...
適切なイベントリスナーを使用しているかどうかや、高さの設定方法などがわかりません。
そして、私は実際にはインラインスタイルを設定していません...
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;
スクロールリスナーを追加する1つの方法は、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'));
これにより、scrollYの位置が100以上のときにテキストが「下にスクロール」から「上にスクロール」に変わります。
編集:各スクロールの状態を更新しすぎるのを避けます。ブール値が変更されたときにのみ更新します。
2019年にこの質問を読むである皆さんのために、@ glennreyesの回答を取り、React Hooksを使用してそれを書き直しました。
const [scroll, setScroll] = useState(0)
useEffect(() => {
document.addEventListener("scroll", () => {
const scrollCheck = window.scrollY < 100
if (scrollCheck !== scroll) {
setScroll(scrollCheck)
}
})
})
seStateには2つの要素の配列があります。最初はstate object、次にそれを更新する関数です。
seEffectはcomponentDidmountを置き換えるのに役立ちます。この場合は不要なので、現在記述されている関数はクリーンアップを実行しません。
クリーンアップが不可欠であるとわかった場合は、seEffect内の関数を返すだけです。
包括的に読むことができます こちら 。
更新:
もしあなたがそれをmodularにしたいと感じたならclean upさえするなら、あなたはこのようなことをすることができます:
以下のようにカスタムフックを作成します。
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
}
それは良いです
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'));
私のユースケースでは、@ 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
}
};
フックを呼び出す:
Const component = () => {
// calling our custom hook and optional distance agument.
const scroll = useHasScrolled(250)
}
これは、ランダムなページ要素をスクロールして表示および非表示にするための、別のテイク/私のテイクオンフックアプローチです。
この 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>
);
};