Reputation: 145
I have an gatsby project. On one page I have an Link (provided from gatsby lib, an anchor basically). When I press on that Link I want it to open the new page and scroll to a certain div on Page 2. BUT only if you come to page 2 trough the Link. If I were to refresh page 2, it want it to not scroll to that div.
Also I want the URL on page 2 not to have any hashtags included.
In my Links to property I have added #target (which is the ID of the div on page 2). This works great except that the URL will have #search in it. I would like it to stay at "/hall/fun".
Then we have a really messy solution I have tried but one I dont want to explore if I dont have to:
I have tried having the scroll function in an useEffect on page 2. But then it scrolls all the time. The idea was to then have an onClick on the Link on page 1 to update an clickedState from the initial state false to true. The page 2 component gets the true value from clickedState and carries on to run the scroll function. But that seems like so much work for something so little.
The Link on page 1
<Link className="aTag" to='/hall/fun#search'>
My scroll function on page 2
let Page2 = props => {
const myTargetRef = useRef(null)
useEffect(() => {
myTargetRef.current.scrollIntoView({behavior:"smooth", block:"start"})
}, [])
return (
<div
onChange={e => setKeyValue(e.target.value)}
value={keyValue}
ref={myTargetRef}
/>
)
}
I only get half an solution with either of these answers. Either the url has an hashtag or it scrolls all the time with the function in useEffect.
Upvotes: 1
Views: 2190
Reputation: 80090
You can pass in state
that your target page listens to, then use a scrollTo
to scroll the browser to the target:
import React, { useLayoutEffect } from "react"
import { Link } from "gatsby"
const SomeComponent = () => (
<Link
to="/some/path"
state={{ targetFragment: "scroll-to-me" }}
/>
)
const YourPageComponent = ({ location: { state: { targetFragment }}}) => {
useScrollTo(targetFragment)
return (
<div>Hello, world!</div>
<div>Hello, world!</div>
<div id="scroll-to-me">Target Me!</div>
)
}
const useScrollTo = id => {
useLayoutEffect(() => {
if (id) {
const el = document.getElementById(id)
const top = window.scrollY + el.getBoundingClientRect().top
window.scrollTo({ top, behavior: "smooth" })
}
}, [id])
}
Upvotes: 2
Reputation: 145
Thanks to @technicallynick Ive found a good solution:
In my "page 2" component, i just replace the url without the characters including and following the hashtag.
useEffect(() => {
const hashtag = window.location.hash
if (hashtag) {
const currentURL = window.location.href
const newURL = currentURL.split("#")[0]
window.history.replaceState("", "Lunch", newURL)
}
})
This solves my problem although feels a bit like an small hack. But I will accept this as an answer if noone else has an suggestion?
Upvotes: 0