Set scroll start position in react hooks - reactjs

I want to make scroll only in chosen place.Before that it have to be impossible scroll the website.
const [doStart] = useState({
startScroll: false
});
useLayoutEffect(() => {
const onScroll = () => {
const scrollPos = window.pageYOffset;
if ( scrollPos === 1000) {
doStart(state => ({ ...state, startScroll: true, }));
}
};
window.addEventListener("scroll", onScroll);
return () => window.removeEventListener("scroll", onScroll);
}, [])

Related

react infinite scroll with IntersectionObserver not working

I don't know why the infinite scroll made of react doesn't work.
Here's what I think.
Connected Element Detection
isFetching = true
setTest()
const [isFetching, setIsFetching] = useState(false);
useEffect(() => {
const io = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsFetching(true);
}
});
setIsFetching(false);
});
io.observe(document.getElementById("finish")!);
return () => io.disconnect();
}, []);
useEffect(() => {
if (!isFetching) return;
setTest([...test, 1]);
}, [isFetching, test]);```

React data from useState is not updating in console.log

Why data is not updated in handleKeyUp() in console.log()?
It renders just fine but it's not updating in console.log()
import React, { useState, useEffect } from "react";
import "./styles.css";
export default function App() {
const [data, setData] = useState({
index: 0,
lastChar: null
});
const handleKeyUp = (e) => {
console.log(data);
setData((current) => {
return {
index: current.index + 1,
lastChar: e.key
};
});
};
useEffect(() => {
document.addEventListener("keyup", (e) => handleKeyUp(e));
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, []);
return (
<div className="App">
{data.index}
{data.lastChar}
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
);
}
You're logging data before it's being set by setData
const handleKeyUp = (e) => {
// log data
console.log(data);
// set data
setData((current) => {
return {
index: current.index + 1,
lastChar: e.key
};
});
};
Then you have a useEffect which only fires when the component mounts (because of the empty dependancy array)
useEffect(() => {
document.addEventListener("keyup", (e) => handleKeyUp(e));
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, []);
You can move your console.log to after your useEffect and you'll see the updated value of data
const handleKeyUp = (e) => {
setData((current) => {
return {
index: current.index + 1,
lastChar: e.key
};
});
};
useEffect(() => {
document.addEventListener("keyup", (e) => handleKeyUp(e));
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, []);
console.log(data);
return (
...
your useEffect is doing error here,consider your current code
useEffect(() => {
document.addEventListener("keyup", (e) => handleKeyUp(e));
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, []);
above code will have older reference to handleKeyup which is need to be updated every time handleKey up is updated ,now inorder to do it , you will need to add handleKey up as a dependency of useEffect like this
useEffect(() => {
document.addEventListener("keyup", (e) => handleKeyUp(e));
return () => {
document.removeEventListener("keyup", handleKeyUp);
};
}, [handleKeyUp]);
right now on each render your handleKeyUp will be defined , in order to prevent it you can make use of useCallback hook like this
const handleKeyUp =useCallback( (e) => {
console.log(data);
setData((current) => {
return {
index: current.index + 1,
lastChar: e.key
};
});
},[setData,data]);
hope it will help

useEffect works only after following Link, not for direct link

i've implemented infinite scroll hook for my newspage
const [posts, setPosts] = useState([]);
const [currentOffset, setCurrentOffset] = useState(0);
const [isLoading, setLoading] = useState(true);
const [isFetching, setIsFetching] = useState(false);
let loadThreePosts = () => {
axios.get(`/news?limit=3&offset=${currentOffset}`).then(({ data }) => {
let threePosts = [];
console.log(data);
data.data.forEach((p) => threePosts.push(p));
setPosts((posts) => [...posts, ...threePosts]);
setLoading(false);
});
setCurrentOffset(currentOffset + 3);
};
useEffect(() => {
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
useEffect(() => {
if (!isFetching) return;
fetchMorePosts();
}, [isFetching]);
function handleScroll() {
if (
window.innerHeight + document.documentElement.scrollTop !==
document.documentElement.offsetHeight ||
isFetching
)
return;
setIsFetching(true);
}
function fetchMorePosts() {
setTimeout(() => {
loadThreePosts();
setIsFetching(false);
}, 2000);
}
So if i go to the newspage throw the Link on my site it fetching posts as i need,
but if i paste newspage link in browser address bar it's not fetch anything
Change your code to this:
useEffect(() => {
window.addEventListener("scroll", handleScroll);
handleScroll(); // Call handleScroll function
return () => window.removeEventListener("scroll", handleScroll);
}, []);

When i operate infinity scroll in the mobile view, the scroll goes to the top

I'm using IntersectionObserver to implement an infinite scroll.
It works well in desktop view, but in mobile view, the scroll moves to the top whenever the isVisible of the source code below changes.
This is not what I want to do.
const targetRef = useRef<HTMLDivElement>(null);
const [isVisible, setIsVisible] = useState(false);
const callbackFunction = (entries: IntersectionObserverEntry[]) => {
if (entries[0].isIntersecting) {
setIsVisible(true);
} else {
setIsVisible(false);
}
};
useEffect(() => {
const observer = new IntersectionObserver(callbackFunction, {
root: null,
rootMargin: '1px',
threshold: 0.1,
});
targetRef.current && observer.observe(targetRef.current);
return () => {
observer.disconnect();
};
}, []);
useEffect(() => {
if (!isVisible || cursor === null) return;
dispatch(getDrawings({ userId: Number(profileId), cursor: cursor }))
.unwrap()
.then((res) => {
const { newCursor } = res;
console.log({ newCursor });
setCursor(newCursor);
});
}, [isVisible]);
Can you help me solve this problem?

How to debounce inside a react useLayoutEffect?

When a user is resizing the window, the width shall be set every 1000 ms. I tried to use a lodash debounce, but somehow it is not fired or not fiered with a delay. How do I need to change the code?
My code:
Sandbox
const Viewport = () => {
const [width, setWidth] = useState(0);
useLayoutEffect(() => {
const handleWindowResize = () => {
debounce(() => {
const windowWidth = window.innerWidth;
setWidth(windowWidth);
console.log("windowWidth", windowWidth);
}, 1000);
};
window.addEventListener("resize", handleWindowResize);
handleWindowResize();
return () => window.removeEventListener("resize", handleWindowResize);
}, []);
return <div>Window width: {width}</div>;
};
export default Viewport;
You don't need to wrap the debounce function in another function
useLayoutEffect(() => {
const handleWindowResize = debounce(() => {
const windowWidth = window.innerWidth;
setWidth(windowWidth);
}, 1000);
window.addEventListener("resize", handleWindowResize);
handleWindowResize();
return () => window.removeEventListener("resize", handleWindowResize);
}, []);
debounce already return another function, that you can pass to the event listener directly.

Resources