The Problem :- The scrollIntoView is working fine but, it fails for this scenario when suppose I click on John Doe
it scrolls to that section but now when I scroll to top and select again John Doe
then it does not get scrolled to that particular section Why is this happening ?
Note :- This happens for all the buttons not just for John Doe
In the useEffect
Dependency array I have added the selectedAdvisor
state variable so that whenever it changes then it should scrollIntoView of that section based on the id
Expected Output :- scrollIntoView should work properly even if I scroll to top and then select the element that was already selected example John Doe
Below is my code :-
import React, { useEffect, useState } from "react";
function AdvisorCard() {
return <div className="advisorCard"></div>;
}
export const NewFilterAdvisor = () => {
const [selectedAdvisor, setSelectedAdvisor] = useState("Tony Stark");
useEffect(() => {
let ele = document.getElementById(`${selectedAdvisor}`);
if (ele) {
ele.scrollIntoView({
behavior: "smooth",
block: "center",
});
}
}, [selectedAdvisor]);
return (
<div className="newFilterAdvisorContainer">
<div className="advisorsBtnContainer">
<button
onClick={() => setSelectedAdvisor("Tony Stark")}
className="advisorBtn"
>
Tony Stark
</button>
<button
onClick={() => setSelectedAdvisor("Steve Rogers")}
className="advisorBtn"
>
Steve Rogers
</button>
<button
onClick={() => setSelectedAdvisor("Bruce Banner")}
className="advisorBtn"
>
Bruce Banner
</button>
<button
onClick={() => setSelectedAdvisor("Thor")}
className="advisorBtn"
>
Thor
</button>
<button
onClick={() => setSelectedAdvisor("John Doe")}
className="advisorBtn"
>
John Doe
</button>
</div>
<div id="Tony Stark" className="advisorSection">
<h1 className="advisorCardContainerHeading">Tony's Advisors</h1>
<div className="advisorCardContainer">
<AdvisorCard />
<AdvisorCard />
<AdvisorCard />
</div>
</div>
<div id="Steve Rogers" className="advisorSection">
<h1 className="advisorCardContainerHeading">Steve's Advisors</h1>
<div className="advisorCardContainer">
<AdvisorCard />
<AdvisorCard />
<AdvisorCard />
</div>
</div>
<div id="Bruce Banner" className="advisorSection">
<h1 className="advisorCardContainerHeading">Bruce's Advisors</h1>
<div className="advisorCardContainer">
<AdvisorCard />
<AdvisorCard />
<AdvisorCard />
</div>
</div>
<div id="Thor" className="advisorSection">
<h1 className="advisorCardContainerHeading">Thor's Advisors</h1>
<div className="advisorCardContainer">
<AdvisorCard />
<AdvisorCard />
<AdvisorCard />
</div>
</div>
<div id="John Doe" className="advisorSection">
<h1 className="advisorCardContainerHeading">John's Advisors</h1>
<div className="advisorCardContainer">
<AdvisorCard />
<AdvisorCard />
<AdvisorCard />
</div>
</div>
</div>
);
};
CodeSandBoxLink :- https://codesandbox.io/s/keen-darkness-g42qjw?file=/src/App.js:1443-1470
Where am I going wrong ? please help
2
Answers
The issues is that if you select same item after you scroll up, you’d update the state to the same value and the
useEffect
won’t run. Actually you don’t even need an internal state. This would do just fine:Sometimes we don’t require any state to some action or event. The problem is clicking again in the button won’t update the state due to same value and obviously no render.
I have used
data-
attribute to store the advisor name and function to receiveonclick
event.Below I haven’t used inline function for each
onclick
there also we pass the advisor value but i have used single instance ofScrollIntoView
function can be used to any number ofbutton
‘s.So any update can made easily in one function and better performance.