Skip to content

marcodpt/ring

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

19 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Ring

Minimalist and functional javascript state manager.

Demo License: MIT GitHub Tag bundlejs

❤️ Features

  • ES6 module.
  • Pure functional design.
  • View layer agnostic.
  • Tiny codebase, very understandable.
  • Designed following the principles of UNIX philosophy.
  • Very well tested.
  • Ridiculously small API. After reading this file you will understand Ring better than me.

💡 Showcase

A counter that increments by one every time the user confirms.

Demo

import ring from "https://cdn.jsdelivr.net/gh/marcodpt/ring/index.js"

ring({
  init: 0,
  register: update => ({
    inc: () => update(count => count + 1)
  }),
  view: (count, {inc}) => {
    if (window.confirm(`Count is ${count}. Increment?`)) {
      inc()
    }
  }
})

💯 Examples

  • Counter: Demo Source
  • Todo: Demo Source
  • Clock: Demo Source
  • Stopwatch: Demo Source
  • Lazy DB: Demo Source

📖 API

ring({init, register, view}) => stop

init: _

The initial state of the ring. It can be any type of data.

register: (update, dispatch) => events

It is called before initializing the ring returning the registered events.

update: (state => newState) => ()

Receives a setter to update the state and call view with the newState.

dispatch: (event, ...args) => ()

Triggers a call to a registered event passing ...args to the event.

events: {init, ...events, done}

Events registered at ring initialization by the register function.

init: state => ()

Special event called at startup.

event: (...args) => ()

The function signature of a user-defined event can have any name.

done: state => ()

Special event triggered when stop is called.

view: (state, events) => ()

Updates the view of the ring, it is always called after an update or when starting.

stop: () => ()

Returns a function that stops the ring.

📦 Projects using this module

If your project is not on the list, submit a pull request, it is a way to increase awareness of your project and this module.

  • Merlin: A functional JS framework that values elegance, simplicity and minimalism.

🤝 Contributing

It's a very simple project. Any contribution, any feedback is greatly appreciated.

⭐ Support

If this project was useful to you, consider giving it a star on github, it's a way to increase evidence and attract more contributors.

🙏 Acknowledgment

This work is hugely influenced by these amazing projects:

A huge thank you to all the people who contributed to these projects.

📢 Motivation

I was extremely delighted and impressed with Hyperapp and Raj when I started using them.

But some things started to bother me:

  • view receives dispatch in Raj, which implies that actions are not static, and with each call to view new actions are generated.
  • Hyperapp achieves static actions by placing them outside the app. Which in my opinion breaks the paradigm of a pure, internal execution environment.
  • It's hard to know the state within dispatch calls when it involves concurrent asynchronous calls both in Raj and in Hyperapp.
  • I can't understand Hyperapp's effects API to this day.
  • It's very difficult to separate layout from javascript logic in Hyperapp's views.

What would I want from a state management library?

  • The actions define static events within the app, and these could be called from each other, also functioning as a library.
  • State updates must be explicit and always carry the current state value, regardless of the asynchronous sequence of execution.
  • It will be isolated, tiny, easy to understand and there will be no reason for me to want to modify the API. Without integrating vDom, template engine, routing, and others.

So I decided to try to create my state management library, to serve as a solid foundation for more complex problems.

And I'm happy with the result!