skip to Main Content

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


  1. 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:

    import React from "react";
    import "./styles.css";
    function AdvisorCard() {
      return <div className="advisorCard"></div>;
    }
    export default function App() {
      const handleSelectItem = (id) => {
        let ele = document.getElementById(`${id}`);
        if (ele) {
          ele.scrollIntoView({
            behavior: "smooth",
            block: "center"
          });
        }
      };
    
      return (
        <div className="newFilterAdvisorContainer">
          <div className="advisorsBtnContainer">
            <button
              onClick={() => handleSelectItem("Tony Stark")}
              className="advisorBtn"
            >
              Tony Stark
            </button>
            <button
              onClick={() => handleSelectItem("Steve Rogers")}
              className="advisorBtn"
            >
              Steve Rogers
            </button>
            <button
              onClick={() => handleSelectItem("Bruce Banner")}
              className="advisorBtn"
            >
              Bruce Banner
            </button>
            <button
              onClick={() => handleSelectItem("Thor")}
              className="advisorBtn"
            >
              Thor
            </button>
            <button
              onClick={() => handleSelectItem("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>
      );
    }
    
    
    Login or Signup to reply.
  2. 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 receive onclick event.

    Below I haven’t used inline function for each onclick there also we pass the advisor value but i have used single instance of ScrollIntoView function can be used to any number of button‘s.

    So any update can made easily in one function and better performance.

    import React from "react";
    import "./styles.css";
    function AdvisorCard() {
      return <div className="advisorCard"></div>;
    }
    export default function App() {
    
      function ScrollIntoView(e){
        const selectedAdvisor = e.target.dataset.advisor;
        let ele = document.getElementById(selectedAdvisor);
        if (ele) {
          ele.scrollIntoView({
            behavior: "smooth",
            block: "center"
          });
        }
      }
      return (
        <div className="newFilterAdvisorContainer">
          <div className="advisorsBtnContainer">
            <button
              data-advisor = "Tony Stark"
              onClick={ScrollIntoView}
              className="advisorBtn"
            >
              Tony Stark
            </button>
            <button
              data-advisor = "Steve Rogers"
              onClick={ScrollIntoView}
              className="advisorBtn"
            >
              Steve Rogers
            </button>
            <button
              data-advisor = "Bruce Banner"
              onClick={ScrollIntoView}
              className="advisorBtn"
            >
              Bruce Banner
            </button>
            <button
              data-advisor = "Thor"          
              onClick={ScrollIntoView}
              className="advisorBtn"
            >
              Thor
            </button>
            <button
              data-advisor = "John Doe" 
              onClick={ScrollIntoView}
              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>
      );
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search