DEV Community

Cover image for EventManager - an agnostic alternative to Redux
Chad Steele
Chad Steele

Posted on • Edited on

3

EventManager - an agnostic alternative to Redux

Redux is a VERY powerful tool, if you need it. I have yet to need it. Javascript comes with powerful event management out of the box. Why not use it? I don't like unnecessary complexity or code and hate centralized bloat, dogma, boilerplate or scaffolding in general and so, I wrote the following library... I hope you like it and can use it.

In short, this code enables you to quickly share state or any info between arbitrary components anywhere in the React hierarchy without having to worry about context, props, etc. It also has some fun features like get(event) and echo(event) that enables a newly rendered component to get an old event that fired before it was rendered.

EventManager - a simple javascript class

You can use EventManager with or without React and I recommend making it a singleton global instance (optional, but optimal)

/**
 * EventManager - simplifies events 
 */
export class EventManager {
  constructor(node) {
    this.node = node || this.node || window;
    this.cache = {};  // old events
  }

  //returns the last time this event was dispatched - even prior to your "listener"
  get(event) {
    return this.cache[event];
  }

  //dispatches the last instance of this event
  echo(event) {
    this.dispatch(this.get(event));
  }

  //listen for and respond to events
  addListener(event, handler, useCapture) {
    if (!event) return;

    handler =
      handler ||
      function (e) {
        if (!e) return null;
        return e.details || null;
      };

    this.node.addEventListener(event, handler, useCapture);
  }

  // stop listening
  removeListener(event, handler) {
    if (!event) return;
    this.node.removeEventListener(event, handler);
  }

  //dispatch an event with forgiving syntax
  dispatch(event, params, quiet) {
    if (!event) return;
    if (!event.type) {
      let e = event;
      let n = e.event || e.name || e;
      let p = e.params || e.data || params;
      if (typeof p === 'object') {
        p = Object.assign({}, e.params, e.data, params);
      }
      event = new CustomEvent(n, { detail: p });
    }

    this.node.dispatchEvent(event);
    this.cache[event.type] = event;
    try {
      if (!quiet) log(`dispatch ${event.type}(${event.detail ? JSON.stringify(event.detail) : ''})`);
    } catch (ex) { }
  }
}

React Components

EventHandler

e.g. <EventHandler event="myEventName" handler={onMyEvent}/>

export function EventHandler(props) {

  let complete = (props.event && props.handler);
  if (!complete) {
    throw (new SyntaxError('<EventHandler> is missing required properties.  <EventHandler event="event-name"  handler={func}  />'));
  }

  //manage events
  useEffect(() => {
    //componentDidMount, componentDidChange
    if (complete) events.addListener(props.event, props.handler, props.useCapture);
    return () => {
      //componentWillUnmount
      events.removeListener(props.event, props.handler);
    };
  });

  return props.children || null;
}

For example, a simple event handler might look like...

    const onMyEvent = e => {
        setDetails(e.detail);
    }

Dispatch

e.g. <Dispatch event="myEventName" expr={a < b} wait={1000} />
If (expr) dispatch an event when something is (re)rendered and/or after a wait period.

export function Dispatch(props) {
  var expr = props.if || props.expr;
  expr = expr == null ? true : expr;
  var wait = props.wait || props.delay || 0;
  useEffect(() => {
    if (expr && props.event) {
      setTimeout(function () {
        events.dispatch(props.event, props.params);
      }, wait);
    }
  });
  return props.children || null;
}

In closing, I do plan to add these to git, npm, etc. someday, but for now I'd appreciate your feedback and especially if you find this useful. Please don't bother defending or evangelizing Redux or strict typing. They're both great and that's not the point of this post. I'm a weird C++'r who actually likes javascript "duck typing" and hope to use it powerfully.

Sincerely,
Chad Steele

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay