Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NextJs Link to another page and then scroll using: react-scroll

I am using react Next js Link element:

import Link from 'next/link';

and also some buttons in my app that scroll to an element when clicked using:

import { Link } from 'react-scroll';

https://www.npmjs.com/package/react-scroll

Both work good separate, But I have one Link that go to another page and I want to scroll after: The link should work like that:

  1. if the user is on the page that this link should link to - it should only scroll to the element.
  2. if the user is on any other page, the link should change page and then scroll to the element.

How can I catch page changes and know if this link was clicked then scroll? Or any other way to solve it?

like image 413
Yuval Levy Avatar asked Oct 25 '25 17:10

Yuval Levy


2 Answers

I did it this way:

index.js

When state (scrollToElement) at redux is changing , then scroll to the element

import {useDispatch, useSelector} from "react-redux"
import {  Element, scroller }from 'react-scroll'
import {ScrollToElement} from "../src/redux/actions/actions"

const dispatch = useDispatch()
const {scrollToElement} = useSelector(state=>state.app)

useEffect(()=>{
   if (scrollToElement){
     scroller.scrollTo(scrollToElement, {
       duration: 800,
       delay: 0,
       smooth: 'easeInOutQuart'
     })
     dispatch(ScrollToElement(null))
   }

},[scrollToElement])

return (
<Element name="YOUR_DIV_NAME" className="element">
<div>SCROLL HERE</div>
</Element>
)

menu.js

Go by Link and change redux state

import { useDispatch } from "react-redux"
import Link from "next/link"

const dispatch = useDispatch()

return (
<Link scroll={false} href="/" >
<li onClick={()=>dispatch(ScrollToElement("YOUR_DIV_NAME"))}>
<a>
Scroll!!
</a>
</li >
</Link>
)

Action.js

export const ScrollToElement = (string) =>{
return  dispatch=>{
    dispatch({type:scrollToElement,payload:string})
}}

AppReducer.js

const initialState = {
scrollToElement:null
}
export const appReducer = ( state = initialState,action ) =>{
switch (action.type){
    case scrollToElement:{
        return {
            ...state,
            scrollToElement: action.payload
        }
    }
   }
like image 55
Roman Zozyla Avatar answered Oct 28 '25 07:10

Roman Zozyla


I solved it with a query parameter and useEffect()

/post/index.tsx

import { useEffect } from 'react';

import type { NextPage } from 'next';
import { useRouter } from 'next/router';
import * as Scroll from 'react-scroll';

const { Element: ScrollElement } = Scroll;

const Post: NextPage = () => {
  const { query } = useRouter();

  useEffect(() => {
    if (query.id === 'targetElement') {
      setTimeout(() => {
        Scroll.scroller.scrollTo('targetElement', {
          duration: 300,
          smooth: true,
          offset: -100,
        });
      }, 100);
    }
  }, [query]);

  return (
    <>
      <ScrollElement
        id="targetElement"
        name="targetElement"
      >
        Target Element
      </ScrollElement>
    </>
  );
};

export default Post;

example.tsx

<Link
  href={{
    pathname: '/post',
    query: { id: 'targetElement' },
  }}
>
  <a>To Target Element</a>
</Link>
)}
like image 32
sect Avatar answered Oct 28 '25 08:10

sect