Skip to content

Latest commit

 

History

History
78 lines (65 loc) · 2.75 KB

12.event-switch.md

File metadata and controls

78 lines (65 loc) · 2.75 KB

Event Switch

When writing event handlers it’s common to adopt the handle{eventName} naming convention.

handleClick(e) { /* do something */ }

For components that handle several event types, these function names can be repetitive. The names themselves might not provide much value, as they simply proxy to other actions/functions.

handleClick() { require("./actions/doStuff")(/* action stuff */) }
handleMouseEnter() { this.setState({ hovered: true }) }
handleMouseLeave() { this.setState({ hovered: false }) }

Consider writing a single event handler for your component and switching on event.type.

handleEvent({type}) {
  switch(type) {
    case "click":
      return require("./actions/doStuff")(/* action dates */)
    case "mouseenter":
      return this.setState({ hovered: true })
    case "mouseleave":
      return this.setState({ hovered: false })
    default:
      return console.warn(`No case for event type "${type}"`)
  }
}

An alternative to the switch statement would be to use an event handlers hash map.

const handlers = {
  click: () => require("./actions/doStuff")(/* action dates */),
  mouseenter: () => this.setState({ hovered: true }),
  mouseleave: () => this.setState({ hovered: false }),
  default: () => console.warn(`No case for event type "${type}"`)
};

You would then have your handleEvent function check if the event type has a corresponding handler, in the handlers object, otherwise use the default case. This way, you don't have to modify handleEvent each time you need to handle a new event.

handleEvent({type}) {
    // Avoid mouseEnter, MouseLeave, Click
    const NORMALIZED_TYPE = type.toLowerCase();

    // If we have no registered handlers, we always use the 'default'
    const HANDLER_TO_CALL = NORMALIZED_TYPE in handlers ? NORMALIZED_TYPE : 'default';

    // No matter how many handlers we end up having in our `handlers` map, this code doesn't modify
    handlers[HANDLER_TO_CALL].call(this);
}

You may also use try..catch and avoid performing key lookups to validate handler presence

handleEvent({type}) {
  try {
    handlers[type.toLowerCase()].call(this);
  } catch (e) {
    handlers['default'].call(this);
  }
}

Note that you have to bind your handler to the component — handler.bind(this) — before calling it. This makes sure that this doesn't point to the handlers object when one of the functions is invoked.

Alternatively, for simple components, you can call imported actions/functions directly from components, using arrow functions.

<div onClick={() => someImportedAction({ action: "DO_STUFF" })}

Don’t fret about performance optimizations until you have problems. Seriously don’t.