Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React scroll component to view inside overflow hidden element

I have a list which contains a series of items, but I can't get it to scroll another item into view. Solutions such as this doesn't quite work, because I have to scroll up and down (basically if the list is too large, scroll it at intervals to display all items).

I made a codepen that illustrates the problem with react-scroll-to-component, but I am open to any library / native solution. The basic functionality is just scrollToComponent(ref, <options>).

The error as far as I can tell is that it attempts to scroll on the body, rather than the actual container. If you remove the height / overflow properties of the div, it will work.

Doesn't work:

<div
    style={{
    height: `200px`,
    overflow: "hidden"
    }}
>
    {this.state.items.map(item => (
    <Item ref={inst => (this[`ref_${item}`] = inst)} item={item} />
    ))}
</div>

Works:

<div>
    {this.state.items.map(item => (
    <Item ref={inst => (this[`ref_${item}`] = inst)} item={item} />
    ))}
</div>

Full code for anyone not wanting to go to codepen:

class Item extends React.Component {
  render() {
    return <div style={{ padding: `12px` }}>Item {this.props.item}</div>;
  }
}

class List extends React.Component {
  state = {
    items: [
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9,
      10,
      11,
      12,
      13,
      14,
      15,
      16,
      17,
      18,
      19,
      20
    ]
  };

  componendDidMount() {
    this.state.items.forEach(item => (this[`ref_${item}`] = React.createRef()));
  }

  onClick = () => {
    scrollToComponent(this.ref_20);
  };

  render() {
    const { items } = this.state;
    return (
      <div>
        <h1>My List</h1>
        <button onClick={this.onClick}>Clickidy</button>
        {/*Replace with <div> to see it work*/}
        <div
          style={{
            height: `200px`,
            overflow: "hidden",
            backgroundColor: "red"
          }}
        >
          {this.state.items.map(item => (
            <Item ref={inst => (this[`ref_${item}`] = inst)} item={item} />
          ))}
        </div>
      </div>
    );
  }
}
like image 517
Dennis Avatar asked Apr 25 '26 19:04

Dennis


1 Answers

I'm going to give you a simple fix but this is how it works. You will need to set the overflow of the div containing all the elements to scroll. This is because if you set it to hidden all elements that are can't fit into that div get hidden. The solution I'm giving you doesn't require even using react-scroll-to-component or any package.

import React from "react";
import { render } from "react-dom";

class Item extends React.Component {
  render() {
    const { item } = this.props;
    return (
      <div style={{ padding: `12px` }} id={item}>
        Item {item}
      </div>
    );
  }
}

class List extends React.Component {
  state = {
    items: [
      1,
      2,
      3,
      4,
      5,
      6,
      7,
      8,
      9,
      10,
      11,
      12,
      13,
      14,
      15,
      16,
      17,
      18,
      19,
      20
    ]
  };


  onClick = () => {
    /** You can avoid using getElementById if you can get the div rendered by Item component using refs.
     * You can look at refs forwarding and other technics to see how you can solve this */
    const divToScrollTo = document.getElementById(`${this.ref_20.props.item}`);
    if (divToScrollTo) {
      divToScrollTo.scrollIntoView();
    }
  };

  render() {
    const { items } = this.state;
    return (
      <div>
        <h1>My List</h1>
        <button onClick={this.onClick}>Clickidy</button>
        <div
          style={{
            height: `200px`,
            overflow: "scroll",
            backgroundColor: "red"
          }}
        >
          {this.state.items.map(item => (
            <Item ref={inst => (this[`ref_${item}`] = inst)} item={item} />
          ))}
        </div>
      </div>
    );
  }
}

Or you can click the link below for the code pen solution https://codesandbox.io/s/2vo0j2w660

I haven't done more optimisations which are required in your code because I'm time bad but hope this helps

Its even easier if you used refs forwarding as shown at code pen here https://codesandbox.io/s/yjj66xl2v1 but you have to create refs in the constructor method`

like image 149
Jjagwe Dennis Avatar answered Apr 28 '26 09:04

Jjagwe Dennis



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!