How To Implement A Scrollspy With React
I want to implement a scrollspy without the bootstrap.  I have checked a lot of code online, all of them are implemented by jQuery. How to implement the scrollspy only with the pow
Solution 1:
I've made a React Wrapper (used with Render-Props):
⚡ Live Codepen Example
const {useState, useEffect, useCallback, useRef} = React;
/**
 *
 * @param {Object} scrollParent [DOM node of scrollable element]
 * @param {Array} _targetElements [Array of nodes to spy on]
 */constspyScroll = (scrollParent, _targetElements) => {
  if (!scrollParent) returnfalse;
  // create an Object with all children that has data-name attributeconst targetElements =
    _targetElements ||
    [...scrollParent.children].reduce(
      (map, item) =>
        item.dataset.name ? { [item.dataset.name]: item, ...map } : map,
      {}
    );
  let bestMatch = {};
  for (const sectionName in targetElements) {
    if (Object.prototype.hasOwnProperty.call(targetElements, sectionName)) {
      const domElm = targetElements[sectionName];
      const delta = Math.abs(scrollParent.scrollTop - domElm.offsetTop); // check distance from top, takig scroll into accountif (!bestMatch.sectionName) 
        bestMatch = { sectionName, delta };
      // check which delet is closest to "0"if (delta < bestMatch.delta) {
        bestMatch = { sectionName, delta };
      }
    }
  }
  // update state with best-fit sectionreturn bestMatch.sectionName;
};
/**
 * Given a parent element ref, this render-props function returns
 * which of the parent's sections is currently scrolled into view
 * @param {Object} sectionsWrapperRef [Scrollable parent node React ref Object]
 */constCurrentScrolledSection = ({ sectionsWrapperRef, children }) => {
  const [currentSection, setCurrentSection] = useState();
  // adding the scroll event listener inside this component, and NOT the parent component, to prever re-rendering of the parent component when// the scroll listener is fired and the state is updated, which causes noticable lag.useEffect(() => {
    const wrapperElm = sectionsWrapperRef.current;
    if (wrapperElm) {
      wrapperElm.addEventListener('scroll', e =>setCurrentSection(spyScroll(e.target)));
      setCurrentSection(spyScroll(wrapperElm));
    }
    // unbindreturn() => wrapperElm.removeEventListener('scroll', throttledOnScroll)
  }, []);
  returnchildren({ currentSection });
};
functionApp(){
  const sectionsWrapperRef = useRef()
  return<CurrentScrolledSectionsectionsWrapperRef={sectionsWrapperRef}>
    {({ currentSection }) => <divref={sectionsWrapperRef}><sectiondata-name="section-a"className={currentSection === "section-a" ? 'active' : ''}
    >Section A</section><sectiondata-name="section-b"className={currentSection === "section-b" ? 'active' : ''}
    >Section B</section><sectiondata-name="section-c"className={currentSection === "section-c" ? 'active' : ''}
    >Section C</section></div>
  }
  </CurrentScrolledSection>
}
ReactDOM.render(
  <App />,
  document.getElementById('root')
)html, body, #root{ height: 95%; overflow:hidden; }
#root > div{ 
  padding-bottom:20em; 
  height: 100%; 
  overflow:auto; 
  box-sizing: border-box;
}
section{ 
  height: 50vh;
  border-bottom: 1px solid red;
}
section.active{ background:lightyellow; }<scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react/16.10.0/umd/react.production.min.js"></script><scriptsrc="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.10.0/umd/react-dom.production.min.js"></script><divid='root'></div>It's not perfect because scroll direction does matter, since it implies on the intentions of the user.
Solution 2:
Live running Demo
https://codesandbox.io/s/gallant-wing-ue2ks
Steps
1. Add the dependency
using npm
npm i react-scrollspy
or using yarn
yarn add react-scrollspy
2. Create your HTML sections
<sectionid="section-1"><!-- Content goes here --></section><sectionid="section-2"><!-- Content goes here --></section><!-- .... --><sectionid="section-n"><!-- Content goes here --></section>3. Add those section's ID to Scrollspy items
<Scrollspy items={ ['section-1', 'section-2', ..., 'section-n'] } />
4. Add some styles
Check this documentation https://makotot.github.io/react-scrollspy/#section-3
Solution 3:
Check out react-ui-scrollspy it is very easy to use.
Full disclosure: I maintain this package.
- In your navigation component
<div><pdata-to-scrollspy-id="first">Section 1</p><pdata-to-scrollspy-id="second">Section 2</p></div>- Wrap the elements you want to spy on in the <ScrollSpy>component.
importScrollSpyfrom"react-ui-scrollspy";
<ScrollSpy><divid="first">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut dolores
    veritatis doloremque fugit. Soluta aperiam atque inventore deleniti,
    voluptatibus non fuga eos magni natus vel, rerum excepturi expedita.
    Tempore, vero!
  </div><divid="second">
    Lorem ipsum dolor sit amet consectetur adipisicing elit. Aut dolores
    veritatis doloremque fugit. Soluta aperiam atque inventore deleniti,
    voluptatibus non fuga eos magni natus vel, rerum excepturi expedita.
    Tempore, vero!
  </div></ScrollSpy>- Write styles for when the navigation element which is active in your index.css
.active-scroll-spy {
  background-color: yellowgreen;
  border-radius: 15px;
}
Solution 4:
You can use React-scrollspy. Visit this git repo React-scrollspy.
Solution 5:
Try to Use npm of 'react-scrollspy-nav' and follow its doc. link
Post a Comment for "How To Implement A Scrollspy With React"