我当前正在尝试在导航栏中获取导航项,以在用户滚动到页面的某些部分时切换类。我的代码使用的是redux,因此当用户滚动到页面的x部分时,我向redux分配了一个操作,该操作随后更改了导航栏的类。但是,随着用户滚动,我的代码对redux的调用太多了,这减慢了用户在导航栏中看到更改的速度。我尝试使用节流阀限制设置Redux状态的调用次数。但这只起作用了一点(仍然有太多的呼叫在进行)。这是我用于更多上下文的代码:
// on scroll change active classes in navbar
useEffect(() => {
const handleScroll = (event) => {
const throttleFunc = throttle(9999999, false, () => {
// fill info
if (
props.readCarefullySect.current.getBoundingClientRect().top > 150 &&
props.stageData.navTwo !== "active" &&
!stage.fillInfo
) {
setStage({
fillInfo: true,
readCarefully: false,
signature: false,
});
props.activeFillInfo();
}
// signature
else if (
props.readCarefullySect.current.getBoundingClientRect().top < -3555 &&
props.stageData.navFour !== "active" &&
!stage.signature
) {
setStage({
fillInfo: false,
readCarefully: false,
signature: true,
});
props.activeSignature();
}
// read carefully
else if (
props.readCarefullySect.current.getBoundingClientRect().top <= 150 &&
props.readCarefullySect.current.getBoundingClientRect().top >= -3555 &&
props.stageData.navThree !== "active" &&
!stage.readCarefully
) {
setStage({
fillInfo: false,
readCarefully: true,
signature: false,
});
console.log("stage in read carefully", stage);
props.activeReadCarefully();
}
});
throttleFunc();
};
window.addEventListener("scroll", handleScroll);
}, [props, stage]);
因为节流阀似乎不像我想的那样起作用,所以我尝试将每个称为“ stage”的对象添加到每个条件中,该对象应根据用户滚动到的位置而改变。想法是,如果阶段已经设置为等于用户所在的部分,则不应将操作分派到redux
当我在每个if语句中进行console.log(stage)时,如果if语句在正确的位置被命中,但是该阶段表明用户所在的上一个位置的正确/错误。例如,我的应用程序的阶段是(从上到下)填充信息,仔细阅读,签名,当用户从填充信息滚动以仔细阅读时,当前阶段为:
{ fillInfo: true, readCarefully: false, signature: false }
但应等于
{ fillInfo: false, readCarefully: true, signature: false }
同样,如果用户再次向上滚动,则阶段等于
{ fillInfo: false, readCarefully: true, signature: false }
但应等于
{ fillInfo: true, readCarefully: false, signature: false }
一定是我在做/不做的事情导致了问题。我对React还是相当陌生,因此非常感谢您的见识
答案 0 :(得分:0)
我猜你的节流功能是一个反跳功能,下面是如何执行此操作的示例,当效果再次运行时,还需要删除事件监听器:
//call function if inactive for time in milliseconds
const debounce = (fn, time = 1000) => {
let timeOut;
return (...args) => {
clearTimeout(timeOut);
timeOut = setTimeout(() => fn(...args), time);
};
};
const App = () => {
const [scrollPos, setScrollPos] = React.useState();
React.useEffect(() => {
const handleScroll = debounce(() =>
setScrollPos(Math.floor(window.scrollY))
);
window.addEventListener('scroll', handleScroll);
//clean up, scroll listener
return () => window.removeEventListener(handleScroll);
}, []);
return (
<ul>
{new Array(100).fill('').map((_, i) => (
<li key={i}>
scroll position: {scrollPos}
</li>
))}
</ul>
);
};
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>