On each page I have a header that has a ‘Back’ button with functionality to go back to the previous page. Function handleGoBack()
:
import React from 'react';
import { Button, Typography } from "@material-tailwind/react";
import { ArrowLeftIcon } from "@heroicons/react/20/solid";
import { useNavigate } from 'react-router-dom';
const PageHeader = ({ title }) => {
const navigate = useNavigate();
const handleGoBack = () => {
// Redirects the user back to the previous page they came from
navigate(-1);
};
return (
<div className="h-24 flex flex-col">
<div>
<Button variant="text" className="flex gap-2" onClick={handleGoBack}>
<ArrowLeftIcon strokeWidth={2} className="w-4 h-4" />
Back
</Button>
</div>
<div>
<Typography variant="h3" color="black" className="mb-2 mx-4">
{title}
</Typography>
</div>
<hr
className="my-2 border-green-100"
style={{ boxShadow: "0px 2px 4px rgba(0, 0, 0, 0.2)" }}
/>
</div>
);
};
export default PageHeader;
Also, in most pages I have a scrollToTop()
function that actually loads the next page from the beginning (from 0,0 coordinates):
function scrollToTop() {
window.scrollTo(0, 0);
}
Let’s see this example (link to "/records"
, with onClick={scrollToTop)
:
import {
Card,
CardBody,
Typography,
Button,
ListItem,
} from "@material-tailwind/react";
import {
ArrowLongRightIcon,
ChevronRightIcon
} from "@heroicons/react/24/outline";
import React from "react";
import { Link } from "react-router-dom";
export default function LastRecordsCard() {
function scrollToTop() {
window.scrollTo(0, 0);
}
return (
<Card className="w-full shadow-lg">
<CardBody>
<Typography
variant="h5"
color="blue-gray"
className="mb-4 flex items-center justify-between"
>
Last Records
<Link to="/records" onClick={scrollToTop}>
<Button size="sm" variant="text" className="flex gap-2">
View All
<ArrowLongRightIcon strokeWidth={2} className="w-4 h-4" />
</Button>
</Link>
</Typography>
</CardBody>
</Card>
);
}
So the problem I have is that when I go back to the page I came from (by clicking the ‘Back’ button), that page should load/focus on the place where the link that took me to that other page was clicked (the one where there is a ‘Back’) button. That is now not the case because obviously I don’t know how to implement that…
Lets see full example (I will exclude imports because of the boilerplate):
HomePage – we are on the Home page:
function HomePage() {
return (
<>
<div className="overflow-hidden">
<Menu />
<div className="h-6 bg-green-50"></div>
<div className="flex justify-center min-h-screen bg-green-50">
<div className="mt-2">
<div className="mx-6">
<TrendCard />
</div>
<div className="mt-8 mx-6">
<LastRecordsCard />
</div>
</div>
</div>
</div>
</>
);
}
LastRecordsCard
(where the link to the next page is) – on the Home Page, we scroll down to this component and we want to click on the View All link:
export default function LastRecordsCard() {
function scrollToTop() {
window.scrollTo(0, 0);
}
return (
<Card className="w-full shadow-lg">
<CardBody>
<Typography
variant="h5"
color="blue-gray"
className="mb-4 flex items-center justify-between"
>
Last Records
<Link to="/records" onClick={scrollToTop}>
<Button size="sm" variant="text" className="flex gap-2">
View All
<ArrowLongRightIcon strokeWidth={2} className="w-4 h-4" />
</Button>
</Link>
</Typography>
Page that renders on the /records path (RecordsPage
) – new page is loaded:
function RecordsPage() {
return (
<>
<div className="overflow-hidden">
<Menu />
<div className="h-6 bg-green-50"></div>
<div>
<PageHeader title="Records" />
</div>
<div className="flex justify-center min-h-screen bg-green-50">
<div className="mt-2">
<div className="mx-6">
<RecordsList />
</div>
<div>
<PageWidthLayout />
</div>
</div>
</div>
</div>
</>
);
}
export default RecordsPage;
And finally PageHeader
component that is common for almost all headers – we see ‘Back’ button and we want to go back to the previous page on the place where we clicked the ‘View All’ link:
const PageHeader = ({ title }) => {
const navigate = useNavigate();
const handleGoBack = () => {
// Redirects the user back to the previous page they came from
navigate(-1);
};
return (
<div className="h-24 flex flex-col">
<div>
<Button variant="text" className="flex gap-2" onClick={handleGoBack}>
<ArrowLeftIcon strokeWidth={2} className="w-4 h-4" />
Back
</Button>
</div>
<div>
<Typography variant="h3" color="black" className="mb-2 mx-4">
{title}
</Typography>
</div>
<hr
className="my-2 border-green-100"
style={{ boxShadow: "0px 2px 4px rgba(0, 0, 0, 0.2)" }}
/>
</div>
);
};
export default PageHeader;
Any idea how to solve this? I’ve been stuck on this functionality for days, but no matter what I do, I can’t move from the dead spot.
2
Answers
So i found that
scrollToTop()
function was responsible for the strange behavior. I followed Muhammad Idrees answer and found that I can't store the scrollY because of thescrollToTop
function which automatically stored the scrollY with a value of 0.I deleted that function and did the following:
In the LastRecordCard component I added function from the Muhammad Idrees answer:
But in the same component, I used only that function in the link:
In the PageHeader component I wrote this:
In this way, I kept the behavior that the new page automatically scrolls to the top, but if we want to go back, the previous page will be loaded from where we left it.
to implement a behaviour where, when a user clicks the "Back" button and returns to the previous page, the page should scroll to the same position where the user clicked the "View All" link.
When the user clicks the "View All" link, you need to store the current scroll position in the browser’s storage
In the PageHeader component, you can use the stored scroll position to restore the previous position when the user navigates back.