npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

hyperapp-compat

v0.4.0

Published

v2 features in your v1 Hyperapps

Downloads

17

Readme

Hyperapp Compat

Build Status codecov npm

Migrate your Hyperapp v1 project to v2 with console warnings informing you what refactoring you will need to do.

Installation

npm i hyperapp-compat

Getting started

import { h, app } from "hyperapp";
+import withCompat from "hyperapp-compat";

-app(state, actions, view, document.body);
+withCompat(app)({
+  init,
+  view,
+  subscriptions,
+  container: document.body
+});

Some examples are available to show this in action.

Migration steps

Although this package offers helpful messages on the steps needed to prepare your v1 Hyperapp for v2 sometimes it's helpful to identify what order one should attack the problem. The following steps are roughly in order of difficulty and prerequisites. By using this project you will be able to check your work in many of the intermediary states along the way.

Refactor positional app args

Wrap your call to app in a withCompat call and convert the multiple arguments to a steamlined new props object:

// Before
app(state, actions, view, document.body);

// After
withCompat(app)({
  init: () => state,
  actions,
  view,
  container: document.body
});

The state can be initialized with the new init function, but most everything else stays pretty much the same so far.

Flatten nested actions

Hyperapp v1 supports a tree of nested actions but this concept has no equivalent in v2. Now is a good time to flatten this tree in order to make later steps easier on yourself. Remember that you are now operating on the entire state tree and not just a "slice" of it. Should be a fairly mechanical refactor, you got this!

// Before
const actions = {
  counter: {
    down: state => ({ count: state.count - 1 }),
    up: state => ({ count: state.count + 1 })
  }
};
const view = (state, actions) => (
  <div>
    <h1>{state.counter.count}</h1>
    <button onclick={() => actions.counter.down()}>-</button>
    <button onclick={() => actions.counter.up()}>+</button>
  </div>
);

// After
const actions = {
  down: state => ({ count: state.count - 1 }),
  up: state => ({ count: state.count + 1 })
};
const view = (state, actions) => (
  <div>
    <h1>{state.count}</h1>
    <button onclick={() => actions.down()}>-</button>
    <button onclick={() => actions.up()}>+</button>
  </div>
);

Merge no more

In v2 actions will no longer shallow merge partial state objects returned from actions. You will want to use the spread operator, Object.assign, or similar.

// Before
const actions = {
  up: state => ({ count: state.count + 1 })
};

// After
const actions = {
  up: state => ({ ...state, count: state.count + 1 })
};

FX

Actions used for side effects will need to be split up into actions and effects for v2.

Remove wired actions from app and view

You will be delighted to know that the hip new v2 style actions and effects can be imported from anywhere (including dynamically) and directly used in your view - meaning you can now ditch this:

const state = {
  count: 0
};

const actions = {
  down: state => ({ count: state.count - 1 }),
  up: state => ({ count: state.count + 1 })
};

const view = (state, actions) => (
  <div>
    <h1>{state.count}</h1>
    <button onclick={() => actions.down()}>-</button>
    <button onclick={() => actions.up()}>+</button>
  </div>
);

withCompat(app)({
  init: () => state,
  actions,
  view,
  container: document.body
});

And instead write this:

const state = {
  count: 0
};

const Down = state => ({ count: state.count - 1 });
const Up = state => ({ count: state.count + 1 });

const view = state => (
  <div>
    <h1>{state.count}</h1>
    <button onclick={Down}>-</button>
    <button onclick={Up}>+</button>
  </div>
);

withCompat(app)({
  init: () => state,
  view,
  container: document.body
});

Remove lazy components (subviews)

Hyperapp v1 included a feature for components to access the global state and actions known as lazy components (sometimes called subviews). This feature was removed for v2 and so components will only receive the props that are passed into them. This may seem annoying if you are now having to pass props multiple levels deep, however this is more explicit and unmagical. This is also an opportunity to rethink the design of the components in your view and decide if there's a better way to organize things.

Remove interop actions

To accommodate calling actions in reponse to anything other than event listeners attached to nodes in your view v1 returns actions for interop from app. You should use init for calling effects on app start and subscriptions for external events instead.

Remove lifecycle events

Lifecycle events have been removed for Hyperapp v2. For users of this feature replacing them may seem daunting, but luckily there is an issue describing many of the alternatives.

License

Hyperapp Compat is MIT licensed. See LICENSE.