DEV Community

Cover image for Adding Signals to Mithril
artydev
artydev

Posted on

Adding Signals to Mithril

In MithrilJS, reactivity is handled through streams, which are observable values, whereas signals—a similar concept in some frameworks—are not part of Mithril’s API

Here is an implementation called 'mithril-signals' based on the awesome work of Andrea Gianmarchi usignal

Available as npm package : mithril-signals

import { signal, computed, effect, batch } from "https://esm.sh/mithril-signals";
Enter fullscreen mode Exit fullscreen mode
import m from "https://esm.sh/mithril";
import { signal, computed, effect, batch } from "https://esm.sh/mithril-signals";



const product = signal(null);
const isLoading = signal(false);
const error = signal(null);

// 2. Define the fetcher function
const fetchProduct = (id) => {
  isLoading(true);
  error(null);

  m.request({
    method: "GET",
    url: `https://dummyjson.com/products/${id}`,
  })
  .then((result) => {
    // Use batch to update multiple signals at once
    batch(() => {
      product(result);
      isLoading(false);
    });
  })
  .catch((err) => {
    batch(() => {
      error(err.message);
      isLoading(false);
    });
  });
};

// 3. The Component
const ProductView = {
  oninit: () => fetchProduct(1), // Fetch product #1 on load
  view: () => {
    if (isLoading()) return m("p", "Loading...");
    if (error()) return m("p", { style: "color: red" }, `Error: ${error()}`);

    const p = product();
    if (!p) return null;

    return m("div", [
      m("h1", p.title),
      m("img", { src: p.thumbnail, width: "200" }),
      m("p", p.description),
      m("p", m("strong", `Price: $${p.price}`)),

      m("button", { 
        onclick: () => fetchProduct(Math.floor(Math.random() * 100) + 1) 
      }, "Fetch Random Product")
    ]);
  }
};

m.mount(document.getElementById("app"), ProductView);
Enter fullscreen mode Exit fullscreen mode

here is the demo : mithril-signals

Top comments (0)