skip to Main Content

Can anyone come across this or tell me which way to look The problem is that: There is a list of elements (dynamic) and there is a window of a certain size. Is it possible to implement the case that when scrolling this list, the flag would change to true for the elements that are visible.

 let arr = [
    { 1: 2, flag: true },
    { 1: 3, flag: false },
    { 1: 4, flag: false },
    { 1: 5, flag: false },
    { 1: 6, flag: false },
    { 1: 7, flag: false },
    { 1: 8, flag: false },
    { 1: 9, flag: false },
    { 1: 10, flag: false },
    { 1: 11, flag: false },
    { 1: 12, flag: false },
    { 1: 13, flag: false },
    { 1: 14, flag: false },
  ];
  return (
    <div
      style={{
        width: '100px',
        overflow: 'scroll',
        height: '60px',
      }}
    >
      {arr.map((el) => (
        <div key={el[1]}>
          <div style={{backgroundColor: `${el.flag ? 'green' : 'red'}`, margin: '5px 0'}}>{el[1]}</div>
        </div>
      ))}
    </div>
  );

There is a link for general views of the problem: https://stackblitz.com/edit/react-ux1rre?file=src/App.js

Thanks for any advice.

2

Answers


  1. Chosen as BEST ANSWER
    import React, { useEffect, useRef, useState } from 'react';
    let counter = 0;
    export default function App() {
      const [scrollTop, setScrollTop] = useState(0);
      const [state, setState] = useState([
        { 1: 2, color: 'red', checked: false },
        { 1: 3, color: 'red', checked: false },
        { 1: 4, color: 'red', checked: false },
        { 1: 5, color: 'red', checked: false },
        { 1: 6, color: 'red', checked: false },
        { 1: 7, color: 'red', checked: false },
        { 1: 8, color: 'red', checked: false },
        { 1: 9, color: 'red', checked: false },
        { 1: 10, color: 'red', checked: false },
        { 1: 11, color: 'red', checked: false },
        { 1: 12, color: 'red', checked: false },
        { 1: 13, color: 'red', checked: false },
        { 1: 13, color: 'red', checked: false },
      ]);
      const element = useRef<HTMLDivElement>(null);
      const testRef = useRef<HTMLDivElement>(null);
      counter++;
    
      useEffect(() => {
        let options = {
          root: document.querySelector('#scrollArea'),
          rootMargin: '0px',
          threshold: 1.0,
        };
    
        let callback = (entries: [], observer) => {
          entries.forEach((entry, index) => {
            if (entry.isIntersecting) {
              console.log(entry)
              setState((prev) => {
                const newArr = prev.slice();
                if (newArr[index].checked === true) return newArr;
                newArr[index].checked = true;
                return newArr;
              });
            }
          });
        };
    
        const nodes = document.querySelectorAll('.test');
    
        let observer = new IntersectionObserver(callback, options);
        nodes.forEach((node) => {
          observer.observe(node!);
        });
      }, [state]);
    
      return (
        <div
          ref={element}
          style={{
            width: '150px',
            height: '200px',
            overflow: 'auto',
          }}
          // onScroll={(event) => {
          //   setScrollTop(element.current?.scrollTop!);
          //   // console.log(event.target);
          //   // console.log(testRef.current?.);
          // }}
          // id="scrollArea"
          // scrolltop={scrollTop}
        >
          {state.map((el, index) => (
            <div
              key={index}
              className="test"
              ref={testRef}
              style={{ backgroundColor: el.checked ? 'red' : 'green' }}
            >
              <p>{el.color}</p>
            </div>
          ))}
        </div>
      );
    }
    

  2. Add this part of code to the main div and this will tell you the position on scroll.

    From this point you can do the math and know if an item was seen or not by the user.

    onScroll={(e) => {
       console.log(e.target.scrollTop);
    }}
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search