In my React project I use scrolling function to go to the same scroll position after coming back from user page (using scroll ref in div), but when page reloads scroll doesn't go to position, but if I'll mechanically re-render page, it goes to the defined position. So I need one more re-render page to scroll it to position, but should be automatically and not after manually on click. anyone can help how can I fix this issue?
// go back to saved scroll position
const Scrolling = () => {
const pos = localStorage.getItem("webLocal:scrollPosition");
const w = document.getElementById("feed");
return (w.scrollTop = pos);
};
useEffect(() => {
Scrolling();
}, [userList]);
I tried lot of ways, setInterval, useEffect, useMemo etc. with all possible dependencies..
Related
I was trying to build a React Application where the user can Drag any element of the page. But after the page refresh, the element gets back to its original position. How can I achieve the feature that even after a page refresh the dragged element won't get back to its previous position?
So I was trying to get the final position when dragged end. I tried with the event. clientX also with offsetX value. And put this X, and Y coordinates to the initial position of the element so that I can check if its position starts where I left it by dragging. But it seems like It is not holding its previous position.
This is my div. Inside that div, I have an image that I am dragging.
<motion.div
drag
dragMomentum={false}
dragConstraints={{
right: 1200,
}}
initial={{ x: -1, y: 367 }}
ref={myRef}
onDragStart={(event, info) => {
initailPosition(event, info);
}}
onDragEnd={(event, info) => {
finalPosition(event, info);
}}
className={Style.imgCntainer}
>
<img
onPointerDown={(e) => {
dragControls.start(e);
}}
className={Style.file}
src={data[0]?.fileLink}
alt="img"
/>
</motion.div>
And the functions are
const finalPosition = (event, info) => {
console.log("end", info.offset.y, info.offset.x);
}
const initailPosition = (event, info) => {
console.log("start", info.offset.y, info.offset.x);
}
I was trying to find the initial position before dragging the element and the final position after the drag ended. But seems like there is something cause I am not getting the exact position.
The first question is: Why do you need to 'reload' the page while having many things happening on that page? It's because React or Vue or Angular is kind of SPA, which is their purpose to avoid reloading the whole page but re-render the update DOM instead.
Back to your question: the only thing which is not reset when you reload the React page is ref value. So, you can use useRef hook to store the original value, final value for your purpose, but I would encourage you to review your application flow to avoid reload the whole page.
who could help me out?
In my react app, I have 3 pages
1.Homepage
2.Settings page
3.Profile page
When I scroll down in the homepage and I navigate to the profile or settings page, it displays the bottom of these next pages corresponding to where I left the scroll bar in the homepage.
How do I stop react from remembering the scroll point when I navigate.
To scroll to the top, include useEffect() that will scroll the page to the top when that component loads. Include this on each page that you want to scroll to the top on load.
import { useEffect } from "react";
export const Homepage = () => {
useEffect(() => window.scrollTo(0, 0), []);
return (<>Hello, world!</>)
}
Note that the second parameter of useEffect can take a variable so that it runs whenever that variable changes. This could allow you to include this code on a higher-level component that watches for page changes.
useEffect(() => window.scrollTo(0, 0), [page]);
Basically I want to build a page that consists of a weekly calendar. Since the calendar is big I want users to be able to zoom out on it to have an overview and to scroll to the specific hour they want. The problem is that when scrolling the users lose the context of the day they are viewing. Its also important to note that the day is on the left of the page and the scroll is done horizontally.
I built a solution based on window.scrollX that uses a transform to translate the div to the left side of the viewport. This works well in a browser, but unfortunately it doesnt work on mobile. The only way for the translation to be correct is by unzooming the page to maximum on Chrome mobile at least. After trying to debug on Google Chrome responsive design, I see that window.scrollX event holds the value 0 even if the scroll bar is not at the beggining
I would like to know if someone had this problem and have any idea how i should keep a div visible always independently of the zoom and scroll. Note that adding the meta viewport minimum-scale=1 solves the problem but that way I cant unzoom no more.
EDIT:
Here's more info of what I'm doing currently. I'm using react and I have a hook (https://github.com/neo/react-use-scroll-position) that does the following:
useEffect(() => {
let requestRunning = null
function handleScroll () {
if (isBrowser && requestRunning === null) {
requestRunning = window.requestAnimationFrame(() => {
setScrollPosition(getScrollPosition())
requestRunning = null
})
}
}
if (isBrowser) {
window.addEventListener('scroll', handleScroll)
window.addEventListener('touchmove', handleScroll)
return () => {
window.removeEventListener('scroll', handleScroll)
window.removeEventListener('touchmove', handleScroll)
}
}
}, [])
I have changed the getScrollPosition() function to use document.body.getBoundingClientRect() without success, and the original function uses window.scrollX.
Here's a picture of what I want to achieve in mobile:
I get that to work, but by limiting the viewport to disable unzoom. But I want the user to be able to unzoom and scroll horizontally while that div is always on the left side of the visible window. Any ideas/alternatives would be really appreciated!
Currently, on the scroll event, I call the below function. If the component has a scroll bar, this works perfectly, and loadMoreThings() gets called exactly as expected.
loadMoreThings() loads more content into the component, and then the user should be able to scroll to the bottom of the window again, and more content should be loaded etc until there's nothing else to load.
updateScroll(instance) {
let maxHeight = this.scrollHeight - this.clientHeight;
let value = this.scrollTop;
let percent = Math.round(100 * ((maxHeight - value) / maxHeight));
if (percent === 0 && instance.state.isLoaded) {
instance.loadMoreThings();
}
this.scrollTo(0, value);
}
However, if the window/device/etc size is tall enough that everything fits in the component, it doesn't overflow, and this function doesn't work, because there wasn't technically any scroll happening at all, even if the user attempts to scroll.
I thought about using the wheel event instead, but it looks like picking a value to call instance.loadMoreThings() would be completely arbitrary since the wheel value doesn't really relate back to anything as far as I can tell.
How can I change updateScroll() so that even if the initial content doesn't overflow, I can still load some more things when the user tries to scroll past the end of the component?
Hello Coders! I am coding a chat system, I would like the scroll bar to stay at the bottom. In this way when someone sends a message the user would not have to scroll down. I would also like it to start at the bottom of the page load. Additionally, the user can scroll up when needed, but when they scroll back down it locks in place. I have tried many times but for some reason it does not work, I was wondering if anyone has a method of doing this?
I've also have struggled with implementing this for a while. The approach I've ended up with relies on using MutationObservable
MutationObservable allows to watch for DOM changes inside element and perform some actions when deeply nested element is changed (in your case, for example, new comment was rendered):
// chatContainer is reference to your chatContainer element
var isLocked = true;
var mutationObserver = new MutationObserver(() => {
if (isLocked) {
scrollToBottom();
}
});
mutationObserver.observe(chatContainer, {
childList: true,
subtree: true,
attributes: false,
});
This gave me a callback, where I likely had to make chatContainer scroll to the bottom.
Scroll to the bottom implementation could be:
function scrollToBottom() {
chatContainer.scrollTop = 99999999999;
}
To change isLocked flag, I had to listen for user scrolls on chatContainer and update it accordingly:
var LOCK_OFFSET = 25; // how many pixels close to bottom consider scroll to be locked
chatContainer.addEventListener('scroll', handleUserScroll);
function handleUserScroll() {
var scrollFromBottom =
chatContainer.scrollHeight -
chatContainer.scrollTop -
chatContainer.clientHeight; // how many pixels user scrolled up from button of the chat container.
isLocked = scrollFromBottom > LOCK_OFFSET; // set new isLocked. lock, if user is close to the bottom, and unlock, if user is far from the bottom.
});
Hope I've explained the general idea. This approach works fine for me. User scroll listening should be improved with events debouncing. And don't forget to dispose scroll event and mutation observer subscriptions.
This is what I've used in my projects. It works on IE, Edge, Firefox, Chrome and Opera. I'm not sure about Safari.
var a = document.querySelector('#divchat');
a.scrollIntoView(false);
I hope it helps.
There are a lot of answers for this question around.
Here is one of them from Automatically scroll down chat div
The main point of that answer is the variables scrollHeight, scrollTop, and clientHeight can be manipulated.
But basically, to scroll down it is to use container.scrollTop = container.scrollHeight;