pmndrs / use-gesture

👇Bread n butter utility for component-tied mouse/touch gestures in React and Vanilla Javascript.
https://use-gesture.netlify.app
MIT License
8.95k stars 307 forks source link

Allow tree shaking while using gesture start & end handlers #315

Closed robatwilliams closed 3 years ago

robatwilliams commented 3 years ago

Describe the bug There isn't a way to attach start & end handlers while only importing a single gesture. This means you have to import useGesture, which is not as tree-shakeable.

For a project using only the drag events, this means the import cost is ~32kB instead of the ~6kB that's importing useDrag would cost.

Now:

import { useGesture } from 'react-use-gesture';

const bind = useGesture(
  {
    onDrag: state => doSomethingWith(state),
    onDragStart: state => doSomethingWith(state),
    onDragEnd: state => doSomethingWith(state),
  })

Potential:

import { useDrag } from 'react-use-gesture';

const bind = useDrag(
  {
    onDrag: state => doSomethingWith(state),
    onDragStart: state => doSomethingWith(state),
    onDragEnd: state => doSomethingWith(state),
  })

Sandbox or Video n/a

Information:

Checklist:

dbismut commented 3 years ago

I agree that useGesture could be tree-shakable, but I don't think this is necessary. At the moment Start/End handlers rely on state.first and state.last.

In other words:

useDrag( ({ first, last, ...state }) => {
  if (first) onDragStart(state)
  onDrag(state)
  if (last) onDragEnd(state)
})

I was thinking that maybe I could rename first / last in start / end, but I don't think changing the API is necessary. I'm going to close this, but we can discuss in the thread.

robatwilliams commented 3 years ago

That sounds good for start & end handlers. The docs for those properties might do with being improved though.

So I started converting to use the approach in your snippet, and found another use case - native event handlers.

I think that strengthens the case a bit. It would also be good if developers didn't need to know about how to use the state first/last flags to achieve start/end handlers.

My opening post took the angle of making the single-gesture hooks more capable (taking a function or object as first parameter), to avoid using useGesture, but I see you responded from the other angle which is to make useGesture be tree-shakable - which sounds cleaner.

dbismut commented 3 years ago

So I started converting to use the approach in your snippet, and found another use case - native event handlers.

You got me there. But yes, I need to try tree-shaking on useGesture, I'm not exactly sure how to do this cleanly though.

// myHooks.js
import { createUseGesture, DragEngine } from '@use-gesture/react'
export const useGesture = createUseGesture(DragEngine)

// Draggable.js
import { useGesture } from './myHooks'

That would be my first thought, but I'm not very experienced in this, maybe you have some counsel.

robatwilliams commented 3 years ago

Yes, something like that to make useGesture tree-shakeable. As a library user I need to know/care/remember about this stuff to get the benefits, but it's maybe a bit cleaner than making individual hooks accept start/end/native by using a tree-shaken useGesture internally.

dbismut commented 3 years ago

I think I'll still export useGesture from the lib as it is today so that it's easier to prototype. And a this tree-shakable createUseGesture function on top of it for people caring about bundle size optim.

robatwilliams commented 3 years ago

Perhaps reopen this issue, given the above?

dbismut commented 3 years ago

Hi @robatwilliams sorry, a bit late in reopening this but I've been a bit busy at work.

I've just introduced createUseGesture in 10.0.0-beta.11 which you can see in action over here:

https://github.com/pmndrs/use-gesture/blob/07e645de940242d9a64c983675611afd66cc5c0d/demo/src/sandboxes/card-zoom/src/App.jsx#L10

I've not tried to type this yet, (ideally, the hook returned by createUseGesture wouldn't accept gesture handlers that aren't passed to createUseGesture), but I fear it's not going to be easy.

Let me know what you think.