atlassian / react-beautiful-dnd

Beautiful and accessible drag and drop for lists with React
https://react-beautiful-dnd.netlify.app
Other
33.32k stars 2.55k forks source link

how to access ref and programatically scroll in react-beautiful-dnd #1873

Open WJKwok opened 4 years ago

WJKwok commented 4 years ago

What i want to achieve: programatically scroll in react-beautiful-dnd droppable column

if it was a simple react div, i could:

const myref = useRef(null)
const executeScroll = () => {
  myref.current.scrollLeft = 1500;
}

return(
  <div>
    <div 
      className={classes.root} 
      **ref={myref}**
    >
        {filteredData.map((spot) => 
          <SpotCard key={spot.place.id} spot={spot}/>
        )}
    </div>
  <button onClick={executeScroll}/>
  </div>
)

However, after I implemented react-beautiful-dnd, I needed to replace the ref

<Droppable 
  droppableId="1"
  direction="horizontal"
>
  {(provided) => (
    <div 
      className={classes.root} 
      **ref={provided.innerRef}**
      {...provided.droppableProps}>
        {filteredData.map((spot, index) => 
          <SpotCard key={spot.place.id} spot={spot} index={index}/>
        )}
        {provided.placeholder}
    </div>
  )}
</Droppable>

how do i access the ref now to execute the scroll programatically now?

kyeo76 commented 4 years ago

just add another div with your ref

const myRef = useRef(null);

return (
  <Droppable droppableId="1">
    {(provided) => (
      <div ref={provided.innerRef} {...provided.droppableProps}>
        <div ref={myRef}>
          {filteredData.map((spot, index) => 
            <SpotCard key={spot.place.id} spot={spot} index={index} />
          )}
        </div>
        {provided.placeholder}
      </div>
    )}
  </Droppable>
);
WJKwok commented 4 years ago

@jaredt67 That works with being able to programatically scroll. However, the autoscrolling when you want to re-arrange the items within gets disabled :/ Also, moving items(draggables) across droppables becomes screwed up. It's weird how just adding an extra 'div' within the 'div'(with provided.innerRef and provided.droppables) screws thing up.

see a gif of the unexpected behaviour: https://media.giphy.com/media/jtvCQ3ttHkz5tU5CrA/giphy.gif

So i'm wondering if there'a anyway to access provided.innerRef in my function outside the Droppable?

const myref = useRef(null)
const executeScroll = () => {
  myref.current.scrollLeft = 1500;
}

<Droppable 
  droppableId="1"
  direction="horizontal"
>
  {(provided) => {
    myRef = provided.innerRef <----- can i perhaps do something like this? This doesn't work.
    return (<div 
      className={classes.root} 
      **ref={provided.innerRef}**
      {...provided.droppableProps}>
        {filteredData.map((spot, index) => 
          <SpotCard key={spot.place.id} spot={spot} index={index}/>
        )}
        {provided.placeholder}
    </div>)
  }}
</Droppable>
thomas-coldwell commented 3 years ago

Hey folks - came across the need to do this as I had a list of cards I wanted to programmatically paginate through as well as drag and drop to reorder. I ran into the same issue where adding a separate div to control the scroll with a ref just breaks the auto-scroll.

I managed to fix it by using this library to compose the ref supplied by react-beautiful-dnd and an additional ref that I use for programmatically controlling the scroll position - this seems to keep both refs perfectly in sync and allows for the programmatic pagination as well as the auto-scroll! I have put together a codesandbox - hope this helps!!

https://codesandbox.io/s/pagination-drag-and-drop-ck83o?file=/src/App.tsx

jenlai1345 commented 3 years ago

Hey folks - came across the need to do this as I had a list of cards I wanted to programmatically paginate through as well as drag and drop to reorder. I ran into the same issue where adding a separate div to control the scroll with a ref just breaks the auto-scroll.

I managed to fix it by using this library to compose the ref supplied by react-beautiful-dnd and an additional ref that I use for programmatically controlling the scroll position - this seems to keep both refs perfectly in sync and allows for the programmatic pagination as well as the auto-scroll! I have put together a codesandbox - hope this helps!!

https://codesandbox.io/s/pagination-drag-and-drop-ck83o?file=/src/App.tsx

Thank you so much. Your solution totally helped me!