_.throttle 执行 API 不止一次
_.throttle executing API more than once
我有一个 TimeLine 组件,一次呈现 5 个帖子
当用户滚动到页面末尾时,会调用节流函数。
我正在尝试将请求限制为每秒最多一次,但是 API 被调用了多次
我尝试了几种解决方案,例如:
制作一个全局标志,除非超过一定的超时时间,否则不会让您使用该功能“这没有意义,因为我正在使用油门来做到这一点,但我试图检查如果我的实现是错误的
在组件外单独声明油门函数
TimeLine.js
export default function TimeLine() {
const dispatch = useDispatch();
const posts = useSelector(state => state.postReducer.posts);
const loaded = useSelector(state => state.postReducer.loaded);
const TIMEOUT = 1000;
// Loaded keeps track of loaded posts
if(loaded === 0){
API.Post.getAllPosts(loaded)(dispatch);
}
if(loaded > 5){
if(loaded % 5 === 0) window.scrollTo(0, document.body.scrollHeight * 0.6)
}
window.addEventListener('scroll', () => throttledReq(loaded, TIMEOUT, dispatch));
const classes = useStyle();
return (
<div>
<NewPost />
{(posts && posts.length > 0)?posts.map((post, index) => (
<div key={post._id} className={classes.post}>
<Post
currentIndex={index}
{...post.user}
dispatch={dispatch}
postID={post._id}
postContent={post.text}
/>
</div>
)): false}
</div>
);
};
节流功能
const throttledReq = (loaded, TIMEOUT, dispatch) => _.throttle(e => {
const bottomLimit = document.documentElement.offsetHeight - window.innerHeight;
if(document.documentElement.scrollTop === bottomLimit){
API.Post.getAllPosts(loaded)(dispatch);
}
}, TIMEOUT)();
我的要求
每次滚动时,都会触发 dispatch
,这又会重新 运行 组件,添加另一个事件侦听器。这将无限继续下去。
您只希望在第一次呈现组件时添加事件侦听器。您可以使用 useEffect
钩子来做到这一点。
useEffect(() => {
window.addEventListener('scroll', () => throttledReq(loaded, TIMEOUT, dispatch));
}, []);
末尾的空数组表示它没有任何依赖关系,因此每当组件渲染时它只会 运行 一次。每次重新渲染都不会调用回调。
您的 loaded
值也应使用 useEffect
,但在本例中使用 loaded
变量作为依赖项。每次 loaded
更改(以及在第一次渲染时),都会触发回调并评估逻辑。
useEffect(() => {
if (loaded === 0) {
API.Post.getAllPosts(loaded)(dispatch);
}
if (loaded % 5 === 0) {
window.scrollTo(0, document.body.scrollHeight * 0.6)
}
), [loaded]);
由于您试图在到达滚动位置或看到某个元素时调用特定逻辑,因此我建议您看一下 Intersection Observer API,它消除了节流 onscroll
函数。
我有一个 TimeLine 组件,一次呈现 5 个帖子
当用户滚动到页面末尾时,会调用节流函数。
我正在尝试将请求限制为每秒最多一次,但是 API 被调用了多次
我尝试了几种解决方案,例如:
制作一个全局标志,除非超过一定的超时时间,否则不会让您使用该功能“这没有意义,因为我正在使用油门来做到这一点,但我试图检查如果我的实现是错误的
在组件外单独声明油门函数
TimeLine.js
export default function TimeLine() {
const dispatch = useDispatch();
const posts = useSelector(state => state.postReducer.posts);
const loaded = useSelector(state => state.postReducer.loaded);
const TIMEOUT = 1000;
// Loaded keeps track of loaded posts
if(loaded === 0){
API.Post.getAllPosts(loaded)(dispatch);
}
if(loaded > 5){
if(loaded % 5 === 0) window.scrollTo(0, document.body.scrollHeight * 0.6)
}
window.addEventListener('scroll', () => throttledReq(loaded, TIMEOUT, dispatch));
const classes = useStyle();
return (
<div>
<NewPost />
{(posts && posts.length > 0)?posts.map((post, index) => (
<div key={post._id} className={classes.post}>
<Post
currentIndex={index}
{...post.user}
dispatch={dispatch}
postID={post._id}
postContent={post.text}
/>
</div>
)): false}
</div>
);
};
节流功能
const throttledReq = (loaded, TIMEOUT, dispatch) => _.throttle(e => {
const bottomLimit = document.documentElement.offsetHeight - window.innerHeight;
if(document.documentElement.scrollTop === bottomLimit){
API.Post.getAllPosts(loaded)(dispatch);
}
}, TIMEOUT)();
我的要求
每次滚动时,都会触发 dispatch
,这又会重新 运行 组件,添加另一个事件侦听器。这将无限继续下去。
您只希望在第一次呈现组件时添加事件侦听器。您可以使用 useEffect
钩子来做到这一点。
useEffect(() => {
window.addEventListener('scroll', () => throttledReq(loaded, TIMEOUT, dispatch));
}, []);
末尾的空数组表示它没有任何依赖关系,因此每当组件渲染时它只会 运行 一次。每次重新渲染都不会调用回调。
您的 loaded
值也应使用 useEffect
,但在本例中使用 loaded
变量作为依赖项。每次 loaded
更改(以及在第一次渲染时),都会触发回调并评估逻辑。
useEffect(() => {
if (loaded === 0) {
API.Post.getAllPosts(loaded)(dispatch);
}
if (loaded % 5 === 0) {
window.scrollTo(0, document.body.scrollHeight * 0.6)
}
), [loaded]);
由于您试图在到达滚动位置或看到某个元素时调用特定逻辑,因此我建议您看一下 Intersection Observer API,它消除了节流 onscroll
函数。