Skip to content
♻️ Minimal functional Virtual DOM rendering using Preact 🚲
JavaScript
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
src
test
.editorconfig
.eslintignore
.eslintrc
.gitignore
.npmignore
.travis.yml
LICENSE
README.md
package.json
rollup.config.js

README.md

preact-cycle

NPM travis-ci

Minimal functional (-reactive) Virtual DOM rendering using Preact.


Simple Example

View this example on esnextb.in

import { render, h } from 'preact-cycle';
/** @jsx h */

const App = ({ value, mutation }) => (
  <div>
    <p>Value: { value }</p>
    <button onClick={ mutation('value', v => v+1) }>Increment</button>
  </div>
);

render(App, { value: 0 });

To-Do List Example

A simple example, where reducers are just pure functions. Note that TOGGLE mutates state in-place, which works fine but is discouraged.

View this example on CodePen

import { render, h } from 'preact-cycle';
/** @jsx h */

const ADD = ({ text, todos, ...state }) => ({
  todos: todos.concat({ text }),
  text: '',
  ...state
});

const TOGGLE = (state, todo) => {
  todo.done = !todo.done;
  return state;
};

const REMOVE = ({ todos, ...state }, todo) => ({
  todos: todos.filter( t => t!==todo ),
  ...state
});


const TodoList = ({ text, todos, mutate, mutation }) => (
  <div>
    <form onSubmit={mutation(ADD)} action="javascript:">
      <input value={text} onInput={e => mutate('text', e.target.value)} />
      <button action="submit">Add</button>
    </form>
    <ul>
      { todos.map( todo => (
        <li onClick={mutation(TOGGLE, todo)}>
          <input type="checkbox" checked={todo.done} readonly />
          <p>{ todo.text }</p>
          <a onClick={mutation(REMOVE, todo)}></a>
        </li>
      ))}
    </ul>
  </div>
);

render(TodoList, { todos: [] }, document.body);

Component-Based Example

Normal preact components still work great with preact-cycle. As of v0.4, mutate() and mutation() are conveniently available as context properties, which means they are automatically passed down through the VDOM tree. For pure functional components, context is simply passed as a second argument.

A component-based variant of the previous To-Do List example follows, using pure functions and context.

import { h, render } from 'preact-cycle';
/** @jsx h */


/** initial data to populate the store */
const INITIAL_DATA = {
  todos: [
    { text:'Type some text' },
    { text:'...then hit [enter]' },
    { text:'Now you\'re productive!' }
  ]
};

/** Appends a new todo item */
const ADD = ({ todos, text, ...state }) => ({
  todos: todos.concat({ text }),
  text: '',
  ...state
});

/** Remove the given todo item */
const REMOVE = ({ todos, ...state }, todo) => ({
  todos: todos.filter(t => t!==todo),
  ...state
});

/** Toggles the given todo item as done */
const TOGGLE = (state, todo) => {
  todo.done = !todo.done;
};


/** a simple helper to derive a mutated value from an event */
let fromEvent = (prev, e) => e.target.value;


/** The todo list app */
const App = ({ text, todos }) => (
  <div id="app">
    <Form text={text} />
    <ul>{ todos.map( todo => (
      <Item todo={todo} />
    )) }</ul>
  </div>
);

/** New todo entry form */
const Form = ({ text }, { mutation }) => (
  <form onSubmit={mutation(ADD)} action="javascript:">
    <input placeholder="New item..."
      value={text}
      onInput={mutation('text', fromEvent)} />
  </form>
);

/** A single todo list item */
const Item = ({ todo }, { mutation }) => (
  <li onClick={mutation(TOGGLE, todo)} class={{ done: todo.done }}>
    <input type="checkbox" checked={todo.done} readonly />
    <a onClick={mutation(REMOVE, todo)}></a>
    <p>{ todo.text }</p>
  </li>
);

// Kick off the cycle!
render(App, INITIAL_DATA, document.body);

License

MIT

You can’t perform that action at this time.