React에서 시차 효과를 만들기 위해 창 스크롤에서 자체 스타일을 업데이트 해야하는 구성 요소를 만들었습니다.
컴포넌트 render
메소드는 다음과 같습니다.
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>
);
}
React가 구성 요소가 변경되었음을 알지 못하므로 구성 요소가 다시 렌더링되지 않기 때문에 작동하지 않습니다.
itemTranslate
구성 요소의 상태에서 값을 저장 setState
하고 스크롤 콜백을 호출 하려고했습니다 . 그러나 이것은 매우 느리기 때문에 스크롤을 사용할 수 없게 만듭니다.
이 작업을 수행하는 방법에 대한 제안 사항이 있습니까?
답변
리스너는 componentDidMount
한 번만 생성되는 방식으로 바인딩해야합니다 . 스타일을 상태로 저장할 수 있어야합니다. 리스너가 성능 문제의 원인 일 수 있습니다.
이 같은:
componentDidMount: function() {
window.addEventListener('scroll', this.handleScroll);
},
componentWillUnmount: function() {
window.removeEventListener('scroll', this.handleScroll);
},
handleScroll: function(event) {
let scrollTop = event.srcElement.body.scrollTop,
itemTranslate = Math.min(0, scrollTop/3 - 60);
this.setState({
transform: itemTranslate
});
},
답변
https://facebook.github.io/react/docs/events.html#ui-eventsonScroll
에서 React 요소 의 이벤트에 함수를 전달할 수 있습니다 .
<ScrollableComponent
onScroll={this.handleScroll}
/>
비슷한 또 다른 답변 : https : //.com/a/36207913/1255973
답변
반응 형 탐색 표시 줄을 만드는 나의 솔루션
componentDidMount() {
window.addEventListener('scroll', this.handleScroll);
}
componentWillUnmount() {
window.removeEventListener('scroll', this.handleScroll);
}
handleScroll(event) {
if (window.scrollY === 0 && this.state.scrolling === true) {
this.setState({scrolling: false});
}
else if (window.scrollY !== 0 && this.state.scrolling !== true) {
this.setState({scrolling: true});
}
}
<Navbar
style={{color: '#06DCD6', borderWidth: 0, position: this.state.scrolling ? 'fixed' : 'relative', top: 0, width: '100vw', zIndex: 1}}
>
나에게 성능 문제가 없습니다.
답변
Austins 응답을 사용할 때 게으른 동작 / 성능 문제를 발견하고 주석에 언급 된 참조를 사용하는 예제를 원하는 사람을 돕기 위해 스크롤 업 / 다운 아이콘으로 클래스를 토글하는 데 사용한 예제는 다음과 같습니다.
render 메소드에서 :
<i ref={(ref) => this.scrollIcon = ref} className="fa fa-2x fa-chevron-down"></i>
핸들러 메소드에서 :
if (this.scrollIcon !== null) {
if(($(document).scrollTop() + $(window).height() / 2) > ($('body').height() / 2)){
$(this.scrollIcon).attr('class', 'fa fa-2x fa-chevron-up');
}else{
$(this.scrollIcon).attr('class', 'fa fa-2x fa-chevron-down');
}
}
그리고 Austin이 언급 한 것과 같은 방식으로 처리기를 추가 / 제거하십시오.
componentDidMount(){
window.addEventListener('scroll', this.handleScroll);
},
componentWillUnmount(){
window.removeEventListener('scroll', this.handleScroll);
},
심판 에 대한 문서 .
답변
다음과 같이 true를 전달하지 않으면 이벤트 리스너를 성공적으로 추가 할 수 없습니다.
componentDidMount = () => {
window.addEventListener('scroll', this.handleScroll, true);
},
답변
classNames , React 후크 useEffect , useState 및 styled-jsx 를 사용하는 예제 는 다음 과 같습니다 .
import classNames from 'classnames'
import { useEffect, useState } from 'react'
const Header = _ => {
const [ scrolled, setScrolled ] = useState()
const classes = classNames('header', {
scrolled: scrolled,
})
useEffect(_ => {
const handleScroll = _ => {
if (window.pageYOffset > 1) {
setScrolled(true)
} else {
setScrolled(false)
}
}
window.addEventListener('scroll', handleScroll)
return _ => {
window.removeEventListener('scroll', handleScroll)
}
}, [])
return (
<header className={classes}>
<h1>Your website</h1>
<style jsx>{`
.header {
transition: background-color .2s;
}
.header.scrolled {
background-color: rgba(0, 0, 0, .1);
}
`}</style>
</header>
)
}
export default Header
답변
후크
import React, { useEffect, useState } from 'react';
function MyApp () {
const [offset, setOffset] = useState(0);
useEffect(() => {
window.onscroll = () => {
setOffset(window.pageYOffset)
}
}, []);
console.log(offset);
};
