Skip to content

An alternative API for programming components and hook functions with Preact

License

Notifications You must be signed in to change notification settings

js-works/preactive

Repository files navigation

preactive

A R&D project to evaluate an alternative API for developing components with Preact using an alternative to hook functions (called "extensions").
The main advantages of the new API are:

  • No rules of hooks
  • No special linter necessary
  • 100% accurately typeable

Be aware that this project is just for research purposes and is not meant to be used in production.

Installation

git clone https://github.com/js-works/preactive.git
cd preactive
npm install

Running demos

npm run storybook

Examples

Remark: We are using the following naming convention to reduce the amount of noise in the source code (for non-trivial components, where you access the props and the state object very often, that makes quite a difference):

  • p is the variable for the props object
  • s is the variable for a state object

Simple counter

import { render } from 'preact';
import { component } from 'preactive';
import { preset, state } from 'preactive/ext';

const Counter = component('Counter')<{
  initialCount?: number;
  label?: string;
}>((p) => {
  preset(p, {
    initialCount: 0,
    label: 'Counter'
  });

  const [s, set] = state({ count: p.initialCount });
  const increment = () => set.count((it) => it + 1);

  return () => (
    <div>
      <button onClick={increment}>
        {p.label}: {s.count}
      </button>
    </div>
  );
});

render(<Counter />, document.querySelector('#app')!);

Additional example - showing more features

import { h, render } from 'preact';
import { component } from 'preactive';
import { effect, preset, state } from 'preactive/ext';

const Counter = component('Counter')<{
  initialCount?: number;
  label?: string;
}>((p) => {
  preset(p, {
    initialCount: 0,
    label: 'Counter'
  });

  const [s, set] = state({ count: p.initialCount });
  const increment = () => s.count((it) => it + 1);

  effect(
    () => console.log(`Value of "${p.label}": ${s.count}`),
    () => [s.count]
  );

  return () => (
    <div>
      <button onClick={increment}>
        {p.label}: {s.count}
      </button>
    </div>
  );
});

render(<Counter />, document.querySelector('#app')!);

API

Core functions

  • component(displayName, render: props => vnode): ComponentClass
  • component(displayName, init: props => () => vnode): ComponentClass
  • component(displayName): (render: props => vnode) => ComponentClass
  • component(displayName): (init: props => () => vnode) => ComponentClass

Utility functions

  • tbd

Extensions

  • atom(initialValue)
  • state(initialValues)
  • createMemo(calculation, getDependencies)
  • consume(context)
  • effect(action, getDependencies? | null)
  • interval(action, milliseconds)
  • handlePromise(getPromise)
  • preset(props, defaultProps or getDefaultProps)

Project state

This R&D project is in a very early development state

About

An alternative API for programming components and hook functions with Preact

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •