Shopify / draggable

The JavaScript Drag & Drop library your grandparents warned you about.
https://shopify.github.io/draggable
MIT License
17.75k stars 1.08k forks source link

Unable to use this with ReactJS #34

Open ghoshnirmalya opened 6 years ago

ghoshnirmalya commented 6 years ago

I've the following html structure:

<div className="items__food">
  <div className="food food--apple">
    <img src={Apple} alt="Apple" />
  </div>
  <div className="food food--banana">
    <img src={Banana} alt="Banana" />
  </div>
  <div className="food food--bread">
    <img src={Bread} alt="Bread" />
  </div>
</div>

And in my componentDidMount, I'm doing:

new Draggable(document.querySelectorAll('.items__food'))
  .on('drag:start', () => console.log('drag:start'))
  .on('drag:move',  () => console.log('drag:move'))
  .on('drag:stop',  () => console.log('drag:stop'));

However, I'm unable to drag any .food items and as a result, nothing is outputted on the console.

screen shot 2017-10-01 at 8 40 01 am

As you can see that .items__food isn't empty inside the componentDidMount lifecycle hook. Am I missing something here?

fighella commented 6 years ago

Interested to see how to integrate with React - I had some strange behaviour with elements duplicating. :)

alex35mil commented 6 years ago

I don't think you can do this (well, you can, but you shouldn't), b/c react is not aware of what draggable does to your DOM nodes so react is unable to compute valid DOM representation for the next render.

fighella commented 6 years ago

I will park that idea for now then. =) ref: https://reactjs.org/docs/integrating-with-other-libraries.html

sltenorio99 commented 6 years ago

I just encountered the issue with react not being aware of the DOM manipulation draggable does. Since draggable does it on the fly while dragging, there's no way to cancel it (from what I can see) like you can with the alike jQuery UI Sortable and let React do it instead.

jdittrich commented 6 years ago

I would love to have integration with MVVM-libraries, too.

tsov commented 6 years ago

@ghoshnirmalya should definitely work with React. You would also need to override the componentDidUpdate to figure out if, e.g. children elements have changed, or you could see if a sortable:sorted has fired (implementation is up to you). Or you could also just return false within componentDidUpdate which tells react to never re-render.

There are plans on releasing a react component as a separate bundle for this repo.

Since draggable does it on the fly while dragging, there's no way to cancel it

@STenorio99 this is true, Sortable, Swappable and Droppable do DOM manipulations as you drag around, as supposed to on drag end. This makes this draggable library different than others, but we could add a traditional sortable module (built on top of Draggable) that performs DOM manipulation on drag end instead.

You can cancel most DOM manipulations via canceling events, e.g.

new Swappable(containers)
  .on('swappable:swapped', (event) => event.cancel())

We are missing the cancelable action for sortable:sorted, but we can easily add it, which is the plan. It would work like swappable https://github.com/shopify/draggable#events-3

I hope that answered a lot of the questions in this issue?

cheri1977 commented 6 years ago

Awesome

hadifarnoud commented 6 years ago

We are working on React html editor, making it easy to use this library would make our editor a lot more awesome!

pie6k commented 6 years ago

Do you have any, even very basic and simple example of React component using it?

hadifarnoud commented 6 years ago

We do not. that was supposed to be a motivational comment to add react support/docs soon

jefflam commented 6 years ago

While we're at it, what about other frameworks such as VueJS?

ghoshnirmalya commented 6 years ago

@jefflam https://github.com/Shopify/draggable/issues/18.

bondz commented 6 years ago

There are plans on releasing a react component as a separate bundle for this repo.

React support would be awesome.

Diogomartf commented 6 years ago

Yeah, I would love to see React support! Thanks for the library

jmakGH commented 6 years ago

I just threw together a very simple example integrating the Sortable portion of this library with React if anyone wants to check it out for reference.

Repo Demo

fighella commented 6 years ago

That's great. Thanks Justin!

On Fri, Nov 17, 2017 at 4:50 PM, Justin Mak notifications@github.com wrote:

I just threw together a very simple example integrating the Sortable portion of this library with React if anyone wants to check it out for reference.

Repo https://github.com/jmakGH/shopify-draggable-react-example Demo https://jmakgh.github.io/shopify-draggable-react-example/

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/Shopify/draggable/issues/34#issuecomment-345151868, or mute the thread https://github.com/notifications/unsubscribe-auth/AAH9Yk5k6wKIWeZf32ZmSPIJPW3936Jyks5s3R6LgaJpZM4PpxDd .

anztrax commented 6 years ago

wow thanks @jmakGH :+1:

jmakGH commented 6 years ago

No problem guys, although I should note it's definitely a rough draft. The current setup works outside of the React lifecycle, meaning that sorting the blocks only changes the UI representation but not the actual state.

Project is updated and now runs all updates properly through React.

All the hooks are there though to update state accordingly and I'll be getting this more Reactified in the upcoming days as well as getting a few more different examples up.

hadifarnoud commented 6 years ago

@jmakGH thank you so much! I couldn't figure it out by myself

beefchimi commented 6 years ago

@tsov do we want to leave this issue open until we have some official React integration – or would you say its safe to close this?

tsov commented 6 years ago

Let's keep it open until we natively support react or can recommend a 3rd party wrapper library. This is also a good spot for people with the same question

wuweiweiwu commented 6 years ago

@tsov @beefchimi I'm going to start working on a React wrapper for this! :) I'll keep you guys posted

wuweiweiwu commented 6 years ago

Update # 1:

Design for Draggable

Supports single containers

DraggableContainer
    props:
        draggable: string
        handle: string
        as: string // what to render the container as
        className: string // classname for the container
        style: {[string]:string} //inline styling   
        delay: number
        classes: {[string]: string} // add classes to elements to indicate state
        draggableRef: (Draggable) => void // ref so you can access the Draggable object to override stuff if u want. Like event listeners
                 // and all the React synthetic event handlers :) 

Draggable
    context: 
        draggable: string // classnames for the query selector. Added onto classname

    props:
        as: string
        className: string // classname for the component
        style: {[string]:string} //inline style
        children: Nodes // what to render inside (even react components)
                 // and all the React synthetic event handlers :) 

Handle
    context:
        handle: // classnames for the handle. Added onto classname

    props:
        as: string
        className: string // classname for the component
        style: {[string]: string}
                 // and all the React synthetic event handlers :) 

Usage would be like:

<DraggableContainer draggable="whatever" handle="whatever2">
    <Draggable children={<Handle/>} />
</DraggableContainer>

Using the provider pattern to pass the classnames to the respective children without explicitly passing the props in Draggable and Handle. I should have it implemented soon :)

wuweiweiwu commented 6 years ago

Update # 2:

95% DONE!!! :)

repo: https://github.com/wuweiweiwu/react-shopify-draggable

I just need to finish some enzyme tests and flesh out the demos and update the README

Will update soon.

ps: react-shopify-draggable is actually taken on npm already but it just has some boilerplate code that that just create a Draggable instance and nothing else. So I will be publishing it as a scoped module

yarn add @wuweiweiwu/react-shopify-draggable
wuweiweiwu commented 6 years ago

@tsov @beefchimi

Done and published! :)

Repo: https://github.com/wuweiweiwu/react-shopify-draggable Simple Demo: https://weiweiwu.me/react-shopify-draggable/ NPM: https://www.npmjs.com/package/@wuweiweiwu/react-shopify-draggable

Implementation details: https://github.com/wuweiweiwu/react-shopify-draggable#implementation-details on how I was able to pass options down via context. And update props like id className and style without rerendering

@jmakGH I took your example + some styling to create my simple example. And it is pasted below.

render() {
  return (
    <div className="App">
      <div className="App-body">
        <div className="App-body-count">
          <h1 className="App-body-count-text">Block count:</h1>
          <input
            type="number"
            className="App-body-count-input"
            value={this.state.blockCount}
            onChange={this.handleBlockCount}
          />
        </div>
        <DraggableContainer
          as="div"
          type="sortable"
          className="BlockGenerator"
        >
          {Array.from(Array(this.state.blockCount).keys()).map(number => (
            <DraggableItem
              as="div"
              className="Block"
              style={{ backgroundColor: randomColor() }}
            >
              {number}
            </DraggableItem>
          ))}
        </DraggableContainer>
      </div>
    </div>
  );
}

Also working on some more advanced examples in Storybook

I would love any feedback. Enjoy 💯

Luke1298 commented 3 years ago

Any plans on making sortable:sorted cancelable?

tangdw commented 3 years ago

+1

afian commented 1 year ago

If for some reason you don't want to use the awesome react-shopify-draggable, I've written a short tutorial (https://afi.io/blog/how-to-use-shopify-draggable-with-react/) that shows how you can make shopify draggable work with react.