Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to scroll to element of the list in other component?

How to scroll to element of the list in other component?

class Posts extends Components {
  render() {
    <ul>
     {this.props.posts.map((post) => 
        <li key={post.id}>{post.title}</li>
     )} 
    </ul>
  }

   //redux
}

class OtherComponent extends Components {
  onClickHandler = (id) => {
     //!!!!!!!!
     //scroll page to li with key={post.id}
  }

  render() {
    <div>
     {this.props.posts.map((post) => 
        <div key={post.id} onClick={() => this.onClickHandler(post.id)}>{post.title}</div>
     )} 
    </div>
  }

   //redux
}

I found solutions here: ReactJS how to scroll to an element

but all are for single element.

If I have list, I need to create a reference to everyone? The list of posts can change, so I can not do it.

like image 238
tolu Avatar asked Oct 16 '25 03:10

tolu


1 Answers

You can build an index of refs based on the key of the item when iterating over the list, then use that key to lookup the ref and invoke scrollIntoView on the element.

UPDATE: Revised code example now shows how to store the list of refs in a child component and invoke a function on that child component to scroll to a particular item in the list. Using refs, you can call a function on a child component instance. This isn't ideal since it breaks out of React's declarative model, but in some situations, particularly around interacting directly with DOM elements for focus or scrolling, it is needed. If you haven't already I also suggest reading the brief React guide to Refs and the DOM, as well as Forwarding Refs and how they may be helpful.

const items = Array.from(new Array(1000).keys()).map(m => ({
  id: m + 1,
  name: `Item ${m + 1}`
}));

const ComponentA = ({ children, onClick }) => (
  <button type="button" onClick={onClick}>
    {children}
  </button>
);

class ComponentB extends React.Component {
  constructor(props, context) {
    super(props, context);

    this.itemRefs = {};
  }

  scrollTo(id) {
    this.itemRefs[id].scrollIntoView();
  }

  render() {
    return (
      <ul>
        {items.map(m => (
          <li key={m.id} ref={el => (this.itemRefs[m.id] = el)}>
            {m.name}
          </li>
        ))}
      </ul>
    );
  }
}

class App extends React.Component {
  render() {
    return (
      <div>
        <ComponentA onClick={() => this.listComponent.scrollTo(1000)}>
          Jump to Item 1000
        </ComponentA>
        <ComponentB ref={e => (this.listComponent = e)} />
        <ComponentA onClick={() => this.listComponent.scrollTo(1)}>
          Jump to Item 1
        </ComponentA>
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
like image 110
Tyler Avatar answered Oct 17 '25 18:10

Tyler