Home

Awesome

hookedElements 🪝

<sup>Social Media Photo by chuttersnap on Unsplash</sup>

📣 Community Announcement

Please ask questions in the dedicated discussions repository, to help the community around this project grow ♥


This module integrates µhooks in wickedElements for a ~2K all-inclusive package and zero polyfills needed whatsoever.

The compatibility is the same as wickedElements, meaning IE11+ and other Desktop/Mobile browsers.

Live Demo

// define via callback to receives the element right away
import {define, useState} from 'hooked-elements';

define('button.counter', element => {
  const [count, update] = useState(0);
  element.onclick = () => update(count + 1);
  element.textContent = `${count} clicks`;
});

The callback is used as render method and automatically augmented and invoked as soon as the element becomes wicked.

In A Nutshell

All hooks are available, and useEffect is granted to run before disconnected, if it returns a callback to drop the effect.

Live Demo

// define via wickedElements literal, render auto-augmented
import {define, render, useEffect, useState} from 'hooked-elements';

define('button.counter', {
  // if not provided, the init() is automatically defined as such:
  init() {
    // the render augment the current render method once
    // and invokes it right away for the first time
    // the element gets upgraded as "wicked"
    render(this);
  },
  // all other wickedElements goodies are in too,
  // and if there is an effect that returns a callback,
  // that will always be invoked before `disconnected`
  disconnected() {
    console.log(this.element, 'disconnected');
  },
  // the render also receives an element, but you can always
  // retrieve it via `const {element} = this;`
  // please note the element is bound, so that any
  // `this.render()` call will always automatically pass
  // the component element too.
  render(element) {
    useEffect(() => {
      console.log('FX on');
      return () => console.log('FX off');
    });
    const [count, update] = useState(0);
    element.onclick = () => update(count + 1);
    element.textContent = `${count} clicks`;
  }
});

F.A.Q.

<details> <summary> <strong>Can I use 3rd parts libraries to render content?</strong> </summary> <div>

Sure thing! Following a <a href="https://github.com/WebReflection/uhtml#readme">µhtml</a> integration example, also <a href="https://codepen.io/WebReflection/pen/qBdOzWj?editors=0010">live in CodePen</a>:

Live Demo

import {render, html, svg} from 'uhtml';
import {define, useState} from 'hooked-elements';

// as mixin
const MicroHTML = {
  html() { return render(this.element, html.apply(null, arguments)); },
  svg() { return render(this.element, svg.apply(null, arguments)); }
};

define('button.counter', {
  ...MicroHTML,
  render(element) {
    const [count, update] = useState(1);
    element.onclick = () => update(count + 1);
    this.html`Hello 👋 <strong>${count}</strong> times!`;
  }
});

// or straight forward via callback and explicit render
define('my-counter', element => {
  const [count, update] = useState(0);
  render(element, html`
    <button class="large btn" onclick=${() => update(count - 1)}>-</button>
    <span class="large value">${count}</span>
    <button class="large btn" onclick=${() => update(count + 1)}>+</button>
  `);
});
</div> </details> <details> <summary> <strong>How can I use hooks outside the <code>render()</code>?</strong> </summary> <div>

While the render() is the only augmented callback, as hooks changes are usually reflected through the UI, you can compose hooks outside the render method, or assign their state without any issue within such method.

Live Demo

// define via wickedElements literal, render auto-augmented
import {define, useState} from 'hooked-elements';

define('button.counter', {
  render(element) {
    // assign the current counter state
    this.countState = useState(0);

    // use only what you need in here
    const [count] = this.countState;
    element.textContent = `${count} clicks`;
  },

  // handle clicks through such state
  onClick() {
    const [count, update] = this.countState;
    update(count + 1);
  }
});

Simply remember that a wicked component is unreachable, unless exposed otherwise, so that it's always safe to assign at runtime any property to it (it's just an object literal, after all 😉).

</div> </details>