Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

synchronise scroll of two react components without using state and actions

I am trying to sync scroll of two different components in React so that if I scroll one in one component the other component will also scroll. The two are in different ratios so I have to calculate to offsets every time.

I don't want to use state and actions (I am using redux) since it hurts my performance due to re-rendering every mouse scroll (I also tried debouncing/throttling).

I have a wrapper component which renders two other components like so:

class Wrapper extends React.Component {
  render() {
    return (
      <div>
        <FirstComponent />
        <SecondComponent />
      </div>
    );
  }
}

I tried to use ref but it doesn't work on custom components (I get undefined) and in any case this all looks like an anti-pattern for react/redux.

Any suggestion on how to achieve that without hurting performance and staying as close as possible to the React/Redux patterns?

like image 294
David Tzoor Avatar asked Dec 22 '16 20:12

David Tzoor


People also ask

How do I sync my scroll in React?

All you need is to: make <ScrollSync> as a common parent to your nodes you want to sync scroll with other nodes (which is a React component that uses React's new Context API) and then wrap each scrollable-node with a <ScrollSyncNode>

Can you pass state between components React?

Sometimes, you want the state of two components to always change together. To do it, remove state from both of them, move it to their closest common parent, and then pass it down to them via props.

What is synchronizing in React?

Some components need to synchronize with external systems. For example, you might want to control a non-React component based on the React state, set up a server connection, or send an analytics log when a component appears on the screen.

Can you have multiple React components in one file?

We can create as many components as we want in the same file, and we can use those components in the same way as we use HTML tags div, span, p etc.


2 Answers

For similar questions in the future you can look at: react-scroll-sync, which saved my work with very complex table syncing case.

A short example how to use:

<ScrollSync>
<div style={{ display: 'flex', position: 'relative', height: 300 }}>
  <ScrollSyncPane>
    <div style={{overflow: 'auto'}}>
      <section style={{ height: 500 }}>
        <h1>Left Pane Content</h1>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aperiam doloribus
          dolorum
          est eum eveniet exercitationem iste labore minus, neque nobis odit officiis omnis
          possimus quasi rerum sed soluta veritatis.</p>
      </section>
    </div>
  </ScrollSyncPane>

  <ScrollSyncPane>
    <div style={{overflow: 'auto'}}>
      <section style={{ height: 1000 }}>
        <h1>Middle Pane Content</h1>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab aperiam doloribus
          dolorum
          est eum eveniet exercitationem iste labore minus, neque nobis odit officiis omnis
          possimus quasi rerum sed soluta veritatis.</p>
      </section>
    </div>
  </ScrollSyncPane>

</div>
</ScrollSync>
like image 101
Nadezhda Serafimova Avatar answered Sep 30 '22 14:09

Nadezhda Serafimova


I have created this library recently, that solves your issue

All you need is to:

  1. make <ScrollSync> as a common parent to your nodes you want to sync scroll with other nodes (which is a React component that uses React's new Context API)
  2. and then wrap each scrollable-node with a <ScrollSyncNode>

and then the sync happens :D

check this codesandbox

like image 24
Ahmad M. Hawwash Avatar answered Sep 30 '22 14:09

Ahmad M. Hawwash