Faking handleEvent in a (P)react function component

by Peer Reynders

HTML

<div id="app"></div>

CSS

button {
  display: block;
  margin: 0.2rem 0;
}

label {
  display: block;
}

textarea {
  width: 100%;
  height: 19rem;
}

.grandparent {
  padding: 0.8rem;
  border: 2px solid red;
}

.parent {
  padding: 0.8rem;
  border: 2px solid blue;
}

.clickme {
  margin: 0 auto;
}

JavaScript

import { h, render } from 'https://unpkg.com/preact@latest?module';
import {
  useReducer,
  useMemo,
} from 'https://unpkg.com/preact@latest/hooks/dist/hooks.module.js?module';

function toActionType(jsHook) {
  const parts = jsHook.split('-');
  let type = parts[1].toLowerCase();
  for (let i = 2; i < parts.length; i += 1) {
    const part = parts[i];
    type += part[0].toUpperCase() + part.substring(1).toLowerCase();
  }
  return type;
}

function makeHolder(initialPair) {
  const holder = {
    reducerPair: initialPair,
    handleEvent,
  };
  return holder;

  function handleEvent(e) {
    const jsHook = findJsHook(e.currentTarget.classList);
    if (!jsHook) return;

    const reducerPair = holder.reducerPair;
    const [_state, dispatch] = reducerPair;

    switch (jsHook) {
      case 'js-grandparent':
        if (event.type === 'click') clickGrandparent(reducerPair, e);
        return;

      case 'js-parent':
        if (event.type === 'click') clickParent(reducerPair, e);
        return;

      case 'js-clickme':
        if (event.type === 'click') clickButton(reducerPair, e);
        return;

      case 'js-stop-grandparent':
      case 'js-stop-parent':
      case 'js-stop-click':
        if (event.type === 'change')
          dispatch({ type: toActionType(jsHook), payload: e.target.checked });
        return;

      case 'js-clear':
        if (event.type === 'click') log(dispatch, '');
        return;
    }
  }
}

function findJsHook(classList) {
  for (let i = 0; i < classList.length; i += 1) {
    const name = classList.item(i);
    if (name.startsWith('js-')) return name;
  }
}

function clickGrandparent([{ stopGrandparent }, dispatch], e) {
  log(dispatch, 'Handling click via capture on red div');
  console.log('Red Div onClick');
  if (stopGrandparent) e.stopPropagation();
}

function clickParent([{ stopParent }, dispatch], e) {
  log(dispatch, 'Handling click via bubble on blue div');
  console.log('Blue div on Click...');
  if (stopParent)...