Skip to content

Commit

Permalink
Be able to pass an object to Actuator's on prop.
Browse files Browse the repository at this point in the history
  • Loading branch information
molefrog committed Dec 6, 2017
1 parent 8f50b8d commit 1dc440e
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 6 deletions.
27 changes: 27 additions & 0 deletions src/__tests__/Actuator.spec.js
Expand Up @@ -102,4 +102,31 @@ describe('Actuator component', () => {
expect(eventHandler).not.toHaveBeenCalled()
})
})

it('allows to subscribe to multiple chans at once', () => {
const store = createStore()

const handlerA = jest.fn()
const handlerB = jest.fn()
const handlerC = jest.fn()

mount(
<Provider store={store}>
<Actuator
on={{
foo: handlerA,
bar: handlerB,
baz: handlerC
}}
/>
</Provider>
)

store.dispatch(actuate('foo'))
store.dispatch(actuate('bar'))

expect(handlerA).toHaveBeenCalled()
expect(handlerB).toHaveBeenCalled()
expect(handlerC).not.toHaveBeenCalled()
})
})
45 changes: 39 additions & 6 deletions src/components/Actuator.js
Expand Up @@ -13,8 +13,18 @@ export class Actuator extends React.Component {
this._keyCache = {}
}

getChanHandlers() {
const { on, channel } = this.props

if (typeof on === 'function') {
return { [channel]: on }
}

return on
}

getObservedChannels() {
return [this.props.channel]
return Object.keys(this.getChanHandlers())
}

onStateChanged(state = null, ...restOpts) {
Expand All @@ -23,14 +33,20 @@ export class Actuator extends React.Component {

const channels = this.getObservedChannels()

for (let i = 0, chan = channels[i]; i < channels.length; ++i) {
for (let i = 0; i < channels.length; ++i) {
const chan = channels[i]
const event = state.actuator[chan]

if (!event) continue
this.checkEvent(chan, event, ...restOpts)
}
}

callChanHandler(channel, args) {
const handlers = this.getChanHandlers()
handlers[channel] && handlers[channel](...args)
}

checkEvent(channel, event, options = {}) {
// Compare event keys (they have to be unique)
const _prevKey = this._keyCache[channel]
Expand Down Expand Up @@ -58,7 +74,7 @@ export class Actuator extends React.Component {
return
}

this.props.on(...event.args)
this.callChanHandler(channel, event.args)
}

componentDidMount() {
Expand All @@ -84,9 +100,26 @@ export class Actuator extends React.Component {
}

Actuator.propTypes = {
channel: PropTypes.string.isRequired,
on: PropTypes.func.isRequired,
deltaError: PropTypes.number
channel: PropTypes.string,

on: PropTypes.oneOfType([
// Can be simple event handler of a map of handlers
// e.g. { chanOne: ..., chanTwo: ... }
PropTypes.func,
PropTypes.objectOf(PropTypes.func)
]).isRequired,

deltaError: PropTypes.number,

// Always require `channel` prop, unless the map
// of listeners wasn't passed with `on` prop.
_requireChannel: props => {
const isMapOfHandlers = props.on !== null && typeof props.on === 'object'

if (!props.channel && !isMapOfHandlers) {
return new Error('channel is required')
}
}
}

Actuator.contextTypes = {
Expand Down

0 comments on commit 1dc440e

Please sign in to comment.