Polishko
Polishko

Reputation: 3

Moving the scroller of a list container based on the position of an item in React

I have a list container and separate items that open as separate pages/routes. I'm trying to dinamically move the scroller of the container to a desired position based on the element's position. For that I pass a function to the child item that retrieves the position of the item and then in the parent list, after updating the position state I try to set the scroller in useEffect. I have no problem retrieving the item position and setting the current position state in the parent. But the scroller itself never moves. To test with simpler code I checked how the state updates. The parent does re-render and the position does update but scroller position stays the same. I'm a new learner so I must be doing somethiong wrong. I have a separate context for more complex state updates, maybe the way I also update state in the component and not in the provider isn't consistent and interferes with other async state updates (which involve retrieving the list of items with a request from a mock server)?

I'm copying the relevant part of my code:


    function HotelList() {
  const { hotels, filteredHotels, isLoading } = useHotels();
  const [isItemClicked, setIsItemClicked] = useState(false);

  const currHotel = useRef();

  function handleItemClick() {
    setIsItemClicked((oldStatus) => !oldStatus);
  }

  useEffect(
    function () {
      if (currHotel.current) {
        console.log(`I am refreshed and I'm ${currHotel.current}`);
        // Move the scroller 2 pixels each time there is a click
        currHotel.current.scrollTop += 2;
        console.log(currHotel.current.scrollTop);
      }
    },
    [isItemClicked]
  );`


...

 
   return (
    <ul className={styles.hotelList} ref={currHotel}>
      {filteredHotels.map((hotel) => (
        <HotelItem
          hotel={hotel}
          key={hotel.id}
          handleItemClick={handleItemClick}
        />
      ))}
    </ul>
  );

In the item component I simply pass the clickHandling function as props (again only passing the relevant part):

    <li style={{ cursor: "pointer" }} onClick={handleItemClick}>
      <Link
        className={`${styles.hotelItem} ${
          id === currentHotel.id ? styles["hotelItem--active"] : ""
        }`}
        to={`hotels/${id}?lat=${position.lat}&lng=${position.lng}`}
      >

On the console I get this log

I am refreshed and I'm [object HTMLUListElement]
HotelList.jsx:24 2
HotelList.jsx:21 I am refreshed and I'm [object HTMLUListElement]
HotelList.jsx:24 2

Upvotes: 0

Views: 33

Answers (1)

Dev Gorai
Dev Gorai

Reputation: 1

Modify the below useEffect, when useEffect run , it might happend currHotel is not initialised

useEffect(
function () {
  if (currHotel.current) {
    console.log(`I am refreshed and I'm ${currHotel.current}`);
    // Move the scroller 2 pixels each time there is a click
    currHotel.current.scrollTop += 2;
    console.log(currHotel.current.scrollTop);
  }
},
[isItemClicked, currHotel.current]

);`

Upvotes: 0

Related Questions