Giter VIP home page Giter VIP logo

mockstate's Introduction

Deprecated! Use Dutier instead.

Mockstate is a centralized state management for Javascript applications. It provides more control of your state application with a simple and efficiently API and keep the state safe, when the user connection goes offline the state is saved in localStorage to be picked up when the connection back.

๐Ÿ’ See the React.js Todo โžž

npm package CDN

Demos

React.js Todo with Mockstate โžž
Preact.js + Mockstate โžž

Influences

Mockstate provides more control of your application state. It's envolve ideas of Redux and Flux, but explores all power of Promises, doing the work with async action easy.

Getting Started

Install

  • Npm: npm install mockstate
  • Bower: bower install mockstate
  • CDN: https://unpkg.com/[email protected]

Why you should be using Mockstate?

  • More control of you application state.
  • Safe State.
  • It's pure flux, the flow is unidirectional.
  • Tiny API.
  • Actively maintained and being used in production.

The Gist

The application state is stored in an object tree inside a single store. The only way to change the state tree is to emit an action, that always return a Promise. You can receive the result of your action using .then after your dispatch call.

That's it!

import { setState, setActions, subscribe, dispatch } from 'mockstate';

/**
 * Set your store state in a single object.
 */
setState({
 count: 0
})

/**
 * Set your store state in a single object,
 * that always receive the store state as first argument.
 */
setActions({
  increment: ( state, n ) => {
      let count = state.count += n
      return count;
  }
});

/**
 * You can use subscribe() to update your UI in response to state changes.
 * `${this}` can be your UI component, where the subscribe handler will be applied.
 */
subscribe( this, ( data ) => {
  console.log(`Some action was called, Action name: ${data.action} Action Value: ${data.value}.`);
})

/**
 * The only way to mutate the internal state is to dispatch an action.
 * You can receive the response of your action and do something, or not.
 */
dispatch('increment', 1).then( data => {
    console.log(`The result of this action ${data.action} is: ${data.value}`);
})
//1
dispatch('increment', 1);
//2
dispatch('increment', 1);
//3

Simple and efficiently API.

Dispatch

  • Trigger some action for do something. A Promise will be returned, that contain an Object with the
    keys action and value of your correspondent action response.
/**
 * @name dispatch
 * @description Trigger some action.
 * @param {string} actionName Action name
 * @param { arguments } Arguments You can pass the arguments after the actionName
 * @return {Promise} Return a Promise with an Object that contain the value 
 * of the action and the action name. 
 * {value, action} = data;
 */

// On your component
import {dispatch} from 'mockstate';

// You can receive the response of your action and do something, or not.
// If you whant, you can chaining the dispatch Promises.
dispatch('increment', 1)
  .then( data => {
    console.log(`The action will be called. The result is: ${data.value}`);
    return data.value;
  })
  .then( value => {
    console.log(`The response is: ${value}`);
  })

Actions

  • Set your actions functions. Your actions always needs to return a value and receive the state as first argument.
/**
 * @name setActions
 * @description Set the actions functions.
 * @param {object} state The Store State as first argument
 * @param { any } args Other Arguments
 */
 
// actions/index.js
import {setActions} from 'mockstate';

setActions({
  // each action receive the state as first argument
  increment: (state, n) => {
      setTimeout(() => {
        let result = state.count += n;
        return result;
      }, 2000)
  }
});

Store State

  • Set the application Store state
/**
 * @name setState
 * @description Set you application store state
 * @param {object} state Your application state data
 */
 
// store/index.js
import {setState} from 'mockstate';

setState({
  count: 1
});

Getting the Store State

  • Get a state value of your store
/**
 * @name getState
 * @description Get the state value
 * @param {string} stateName The state name
 */
 
// store/index.js
import {getState} from 'mockstate';

let count = getState('count');

Middleware

  • Set a middleware function, that will be triggered after the action calls.
/**
 * @name middleware
 * @description Get the state value
 * @param {Function} callback The callback that will be triggered and
 * receives the data of your action and the all state of your store application.
 */
 
// state/index.js
import { middleware } from 'mockstate';

middleware( (data, state) => {
    console.log('After action triggers:', data, ' and the Store State is: ', state);
})

Emit

  • Tell to store that something are happend and the handler function will be triggerd.
/**
  * @name emit
  * @description Tell to store that something happend,
  * and the handler function will be called.
  * @return void
  **/
 
// state/index.js
import { emit } from 'mockstate';

emit()
  .then( () => {
    console.log('After emit called.');
  });

Subscribe/Unsubscribe

  • Subscribe some UI Component for trigger the handler function when some action are trigger.
  • Unsubscribe when you don't wnat to trigger the handler function.
/**
 * @name subscribe
 * @description Subscribe some UI Component for trigger the handler function when some action calls.
 * @param { object } BindComponent The UI element that the handler function will be applied.
 * @param { handler } handler Your function that will be triggered when some state change.
 */
 
// components/app/index.js
import {subscribe, unsubscribe, getState} from 'mockstate';
  
  componentWillMount(){
     // when some state change, do something.
     subscribe(this, ( data ) => {
       this.setState({count: getState('count')})
     });
  }
  
    componentWillUnmount(){
      // remove this component for observe the changes on the state
      unsubscribe(this)
    }

License

MIT License.

mockstate's People

Contributors

darklow avatar luisvinicius167 avatar marciodsousa avatar ninthspace avatar sharriffaina avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mockstate's Issues

Actions being triggered multiple times

I am building an application using mockstate, and I noticed that quite often I get the same action to be triggered multiple times, although I am pretty sure i only dispatch it once.

Are there any other reports on this? Or does it make any sense even?

I am basically just using dispatch and subscribe. And for one dispatched action I get multiple entries in the subscribe (for the same data.action).

Cannot unsubscribe (el is undefined)

While trying to unsubscribe a component I always get a

Uncaught (in promise) ReferenceError: el is not defined

right here:
unsubscribe: function unsubscribe(component) { var components = Mockstate._store.components; components.forEach**(el,** function (index) { if (el === component) { components.splice(index, 1); } }); },

Seems like bad syntax (el should be before index as a function parameter)

Is it anything you could fix also in npm?

Subscribe handler not being called when performing multiple actions in parallel.

I am witnessing some weird behaviour.
Two of my riot tags are performing riotux actions on mount event. In the same tags I am subscribed to two different state properties. Both actions perform asynchronous calls and when asynchronous task is complete I am dispatching events to change according properties. Both state mutations are called.
The problem is that only one subscribed handler is called.
If I uncomment one or another action, then each of them works well, but not when both running in parallel.

Version 2.0

Working on new version of Riotux. Now, you can dispatch your actions and do something when the Store state was changed. Like this:

import {dispatch} from 'riotux'
dispatch('increment', 1).then( ( newState ) => {
  console.log(`The state was changed. Receive new data: ${newState.action} : ${newState.stateValue}`);
})

Inside your Action, you need return a Promise, and inside your promise you can do what you whant. Like this:

import {setActions} from 'riotux'

setActions({
  increment: (state, n) => {
    return new Promise((resolve, reject) => {
     // your async function
      setTimeout(() => {
        let result = state.count += n;
        resolve(result);
      }, 2000)
    });
  }
});

And you can set your Store state with setState. Your application state is just a simple Object.

import {setState} from 'riotux'

setState({
  count: 0
})

You can see the new work here: Branch new

I'm planning create a Riotux Dev Tools too. :)

Feedbaks are very welcome! Thanks!

Typos, naming and a question

I have seen no example showing the ability to "time travel" like Redux.
'Mutations' Should be called 'Mutators' in my opinion.
riotux.get(state) is better than riotux.getter(state) in my opinion

You have a few typos in the docs. I could send you a pull request to correct them if you want.

What is the reason having state name when calling action?

I can't understand the reason of having state name as first argument when calling action.
Could you please explain little more, because right now I can do in actions whatever I want and set different properties in store and it still works no matter what i provided when calling action. Thank you.

var store = riotux.Store({
  state: {
    todos: [],
    something_else: null
  },
  mutations: {
    something_else: function ( state, value ) {
      state.something_else = value;
    }
  }
})

var actions = riotux.Actions({
  add_todo: function ( store, value ) {
    // Dispatching something else, not related to todos mutations at all.
    store.dispatch('something_else', value);
  }
})

riotux.action('todos', 'add_todo', 'Something');

Usage question on Actions

From the docs:

var action = riotux.Actions({
  add: function ( store, number ) {
    store.dispatch('increment', number);
  }
}); 

Calling an action on your component

riotux.action('count', 'increment', 10);

Is there any reason why the instance of the action is assigned to the "action" variable when it is supposed to be called from the riotux instance?

Cannot provide multiple arguments for trigger method

First of all thanks for the great library.

In RiotJS observables and also in RiotControl when triggering event you can specify unlimited arguments to trigger function and receive them on listener:

// On observable
self.trigger('event', 1, true, {test: 123});
// On listener
obs.on('event', function(num, status, obj){
  // All arguments are present
});

However in riotux only first argument is forwarded to listener and rest of them are dropped.

riotux.trigger('myStore', 'event', 1, 2, 3);
// On myStore:
self.on('event', function (one, two, three) {
  // two and three are undefined :(
});

It would be great if this library had same possibility and since it is built on top of observables I was expecting same behaviour.

I guess it could be easy change, using apply similarly as here:
https://github.com/jimsparkman/RiotControl/blob/master/riotcontrol.js#L15

Although I tried to fix by myself first, but didn't succeeded.

Thanks.

Actions as store functions

nice project, I've written something similar for react-templates, if you mind I would like to hear your opinion on the following ideas:

  1. make actions be true functions on the store itself. So instead of calling the dispatcher with the magic string my_action, you call the function directly (store.my_action(params)). The advantage is to have full intellisense on the action parameters (assuming your IDE does support intellisense). Perhaps the store itself could be an ES6 class to exend.

  2. make the store trigger just one update event when the state changes. The idea is to simplify: you don't want to deal with the details of what part of the state sub-tree has changed, it's enough to know something has changed. So your store could have a "subscribe" function:

store.subscribe(this); // this=riot tag
// on the store:
function subscribe(tag) {
   this.on('update', ()=> tag.update() );
}
function update() {
   this.trigger('update');
}
function my_action() {
   // mutate state
   this.update();
}
  1. you can write a wide range of debugging tools by hooking on the actions and on the update event. For example writing to console what actions have been dispatched, the params, and the state differences before/after (look at packages like deep-diff).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.