Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Compose events helper #32

Closed
souporserious opened this issue Jan 19, 2018 · 4 comments
Closed

Compose events helper #32

souporserious opened this issue Jan 19, 2018 · 4 comments
Assignees

Comments

@souporserious
Copy link
Collaborator

souporserious commented Jan 19, 2018

Would you consider adding a helper utility to help compose events if you want to use the same ones being used by a react-powerplug component?

A contrived example, but I'm using something like this right now:

function composeEvents(internalEvents, externalEvents) {
  return Object.keys(externalEvents).reduce((composedEvents, key) => {
    const internal = internalEvents[key]
    const external = externalEvents[key]
    return {
      ...composedEvents,
      [key]: internal
        ? (event, ...args) => {
            internal(event, ...args)
            external(event, ...args)
          }
        : external,
    }
  }, {})
}

// usage
const HoveredDiv = ({ children, onMouseEnter, onMouseLeave, ...restProps }) => (
  <Hover>
    {({ isHover, bindHover }) => (
      <div
        {...composeEvents({ onMouseEnter, onMouseLeave }, bindHover)}
        {...restProps}
        children={children(isHover)}
      />
    )}
  </Hover>
)
@renatorib
Copy link
Owner

renatorib commented Jan 22, 2018

It's really a nice idea.

I was thinking about it these days while I was planning the Mouse and Scroll components.
Both will use bind funcs with ref

<Scroll>{({ bind }) => ()}</Scroll>
<Mouse>{({ bind }) => ()}</Mouse>

// bind = { ref: Function }

If I try to use both, I'll have a problem:

<Compose components={[Scroll, Mouse]}>
  {(scroll, mouse) => (
    <div {...scroll.bind} {...mouse.bind}>...</div> 
  )}
</Compose>

mouse.bind ref will override scroll.bind ref


My ideia is to have various 'pieces' of events objects.

const composeEvents = (...eventsObjs) => { /* logic */ }
// eventsObjs = [{ onMouseEnter }, { onMouseEnter, ref }, { onMouseEnter, onMouseLeave }, /* etc */]

So we can do that:

<Compose components={[Scroll, Mouse]}>
  {(scroll, mouse) => (
    <div {...composeEvents(scroll.bind, mouse.bind, { ref: another })}>...</div> 
  )}
</Compose>

Some mind draft:

const composeEvents = (...objEvents) => {
  return objEvents.reverse().reduce((acc, events) => {
    let append = {}
    for (const key in events) {
      append[key] = acc[key]
        // already have this event, let's merge
        ? ((...args) => { events[key](...args); acc[key](...args) })
        // don't have this event yet, just assign the event
        : events[key]
    }
    return { ...acc, ...append }
  })
}

const composed = composeEvents({
  onMouseEnter: (event) => console.log('first call', event)
}, {
  onMouseEnter: (event) => console.log('second call', event)
}, { 
  onMouseEnter: (event) => console.log('third call', event),
  onMouseLeave: (event) => console.log(event)
})

composed.onMouseEnter('onMouseEnter event payload')
composed.onMouseLeave('onMouseLeave event payload')

Should be output something like this (in this order)

first call onMouseEnter event payload
second call onMouseEnter event payload
third call onMouseEnter event payload
onMouseLeave event payload

In your use case would be the same you wrote:

const HoveredDiv = ({ children, onMouseEnter, onMouseLeave, ...restProps }) => (
  <Hover>
    {({ isHover, bindHover }) => (
      <div
        {...composeEvents({ onMouseEnter, onMouseLeave }, bindHover)}
        {...restProps}
        children={children(isHover)}
      />
    )}
  </Hover>
)

@souporserious
Copy link
Collaborator Author

Love it! Want me to add a PR? I should have time today or tomorrow.

@renatorib
Copy link
Owner

@souporserious Feel free :D

@renatorib
Copy link
Owner

Fixed in #71

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants