Giter VIP home page Giter VIP logo

stent's Introduction

Stent - brings the power of state machines to the web

Stent is combining the ideas of Redux with the concept of state machines.

Travis npm downloads

Chat: https://gitter.im/stentjs


A few words about state machines

State machine is a mathematical model of computation. It's an abstract concept where the machine may have different states but at a given time fulfills only one of them. It accepts input and based on that (plus its current state) transitions to another state. Isn't it familiar? Yes, it sounds like a front-end application. That's why this model/concept applies nicely to UI development.

Disclaimer: there are different types of state machines. I think the one that makes sense for front-end development is Mealy state machine.

Installation

The library is available as a npm module so npm install stent or yarn add stent will do the job. There's also a standalone version here (only core functionalities) which you can directly add to your page.

Documentaion

Debugging apps made with Stent

Stent is supported by Kuker Chrome extension. Just add the Stent emitter to your app and open the Kuker tab in Chrome's DevTools.

Kuker

Must-read articles/resources

Other libraries dealing with state machines

stent's People

Contributors

alxdarksage avatar aryzing avatar belev avatar illarionvk avatar krasimir avatar mutebg avatar poteirard avatar sofianedjellouli avatar thekarel 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar

stent's Issues

React component does not re-render if state remains and a prop change

Hello.

I'm working on an electrón app that manage folders.

I want that, when the user drops some folders into the app, let's say five, a message shows indicating which folder is being processed.

The way I'm doing it is by not changing the state at all but just sending the same array of folders (these are just objects) with the difference that the current folder has a prop named current set to true, and it gets toggled to every folder being processed.

So, the problem is that, only by passing to the machine a slightly different array, it doesn't re-render the component, and it only do that if I change the state and change it back.

Any hint in how to solve this?

Examples please

I read the article, the git documentation...but I don't know how to implement the state machine (stent( in my project. Any basic project example (more explanatory than the TODO example?)
_

camelCase does not transform underscore `_` character

I find it useful to format state names as URL paths — I can make client-side routing libraries like Reach Router treat the state machine as the location source.

I've noticed that stent does not transform the underscore character when it generates the machine methods, e.g.,

'/initializing/stage_one' --> machine.isInitializingStage_one

Would you consider adopting Lodash approach to camel casing?

_.camelCase('is /initializing/stage_one')
<-- "isInitializingStageOne"

is it possible to use it with redux-saga?

I have the issue when try to use saga effects:
Error: The state should be an object and it should always have at least "name" property. You passed {
"@@redux-saga/IO": true,
"SELECT": {
"args": []
}
}

A new state machine for each instance of a component

First, thanks for creating stent, really intersting pattern.

Did you try / is it possible to use Stent to manage complex component internal state ? I collaborate with Neos CMS (neos.io), and we have some really complex components (image editor, ...) that can gain a lots to have state machine to manage their internal state.

I successfully build a prototype, but as the machine need to be named, all compoment get the same machine, by default.

How to make State Machine table?

In this article,
it demonstrates a SM table in the login form.

But in real cases, it's hard to define the SM table. For instance, I have a user form cantaining 4 inputs
(name, age, company, salary):

<formItem>
    <input name="salary" onBlur={checkSalary}>
    <Hint>{salaryErrHint}</Hint>
</formItem


checkSalary(e) {
    ...
    if (...)
        this.setState({
            salaryErrHint: 'salary is required'
        })
    else if (...)
        this.setState({
            salaryErrHint: 'salary must be a number'
        })
    else if (...)
        this.setState({
            salaryErrHint: 'salary must be less than 10000000'
        })
    else
        this.setState({
            salaryErrHint: ''
        })
}

In above demo I will define 4 errHint states in pure react code.
I want to optimize the code with SM, but I wonder if the below SM chart is appropriate?

UserForm   -->   input.wrong.name     -->  UserForm with nameErrHint
UserForm   -->   input.wrong.age      -->  UserForm with ageErrHint
UserForm   -->   input.wrong.company  -->  UserForm with companyErrHint
UserForm   -->   input.wrong.salary   -->  UserForm with saralyErrHint

I can't see the advantage from the SM table. Thank you in advance.

Uncaught async errors in nested generators

Hi,

Stent generator actions allow us to call other generators. However, if an async error is thrown in one of these nested generators, it will not reach the top-level generator and it won't be caught there.

I added a pull request for it: #55

Make action handlers pure functions

First of all, thanks for creating this library @krasimir, it seems to be a very powerful and expressive solution.

When looking at action handlers I've noticed they are bound to a context. Would you consider making them pure functions, i.e. passing the whole machine as the first argument? (this was mentioned previously in a comment)

So instead of

transitions[state.name][action].apply(machine, [ machine.state, ...payload ])

pass everything as an argument, something like this?

transitions[state.name][action](machine, payload)

The benefit would be having pure functions as handlers, so they would be really easy to unit tests and maybe even a bit more consistent since now parts of the machine are passed as argument (state) and some parts as context (under this).

Handlers would then be able to pick up the relevant bits as in const handler = ({state}) => ({...})

I understand this would be an API breaking change, but maybe something to think about for the future?

[question] how to get additional empty variable inside state

Hi, thank you for your work and your good choice: mealy-machine!

I've a little question, I've create new Machine thats work inside Vue.js!
Now I want to get additional parameter parentAction = new inside the state.

var stent = Machine.create('actions', {
  state: { name: 'start', parentAction: 'new' },
  transitions: {
    'start': {
      'take note': 'note',
      'create ordine': 'order',
      'take party': 'party'
    },
    'note': {
      'take another note': 'note',
      'create order': 'order',
      'take party': 'party'
    },
    'party': {
      'add participant': { name: 'participant', parentAction: 'new' }
    },
    'participant': {
      'create ordine'': 'order',
      'add participant': 'participant',
    },
...

The first state start has stent.state.parentAction = 'new', correct,
but when I change the state to note the stent.state.parentAction is always new.
There is a way to get undefined, null, empty variable for states that haven't stent.state.parentAction defined?

Question: is it possible to execute code "on state change"

Hi,

One question, is it possible to execute code before entering to specific state.

I have a state machine which every state has a transition like next that execute some code (a http request) and then transition to the next state. However I want to check the state before actually reaching that state, let's say to check if the state has X prop.

Is that possible without creating a transition like "checkingState"? Somehow like a specific callback? I saw that I can use middleware but I'm not sure if I can really achieve that like this.

Thank you 👍

componentWillMount is deprecated

Hi. I get warning when using "stent/lib/react":
componentWillMount is deprecated and will be removed in the next major version. Use componentDidMount instead. As a temporary workaround, you can rename to UNSAFE_componentWillMount.

I think we can safely replace componentWillMount with componentDidMount.

Prettier configuration

Would you consider adding a Prettier config to the project to ensure consistent formatting?

impossible to catch the error if a generator function invokes call() with a non-function argument

I get unhelpful errors from Node that slip past the try/catch block if the state action generator function invokes call() helper with an argument that is not a function (see screenshot).

Please take a look at my pull request with a failing test that illustrates the behavior.

I think the call() helper should throw if the argument is not a function before returning the __call object.

P.S. I enjoy working with your library. Thank you for open-sourcing it.

unhelpful-error

failing-test

Camel cased transitions do not produce handlers

While attempting to name a transition startProcess, I found that the connect mappings did not produce a handler for this transition. After renaming it to "start process", the startProcess() handler was mapped as expected.

Are state names not allowed in camel case?

After reading the docs, I was expecting the behavior to be:

  • if spaces exist in transition name -> transform to camel case
  • if dashes exist in transition name -> transform to camel case
  • else -> leave as is

Supporting the ability to have `_enter` and `_exit` actions.

There are many state machines where you need to execute an action on entry into that state. This is especially important for more complex state machines where there may be multiple transitions (from different states) that go into a particular target state. In those cases, you would end up having to write the same code in multiple transitions, which makes maintenance more difficult. Instead, an _entry (or other reserved) action would allow the actions to be consolidated to one place. This also applies for when exiting a state.

I've been able to implement it quite easily (not sure if it is completely correct, since I am bypassing the middleware layer).

What are your thoughts?

generator with 'takeLatest' - is canceling and debouncing possible?

You showed an example with generators:

const machine = Machine.create('todo-app', {
  state: { name: 'idle', todos: [] },
  transitions: {
    'idle': {
      'fetch todos': function * () {
        yield { name: 'fetching' };

        try {
          const todos = yield call(getTodos, '/api/todos');
        } catch (error) {
          return { name: 'error', error };
        }

        return { name: 'done', todos };
      }
    }
  }
});

If I would perform machine.fetchTodos() twice while the async call is still ongoing, the second one is simply discarded.

  • How to model a machine that cancels the first one and fetches again?
  • How to debounce such executions?

Issue when calling action while a generator is awaiting a response and yields after previous action changes state

I'm not sure whether I'm doing something wrong here or misunderstood a concept, so please correct me if I'm on the wrong path here.

I have a machine with an idle state which has a couple of transitions:
handle password, handle email -> they all just update the idle states current data (so that username etc. are updated).
Then there's a "handle username" transition which is a generator function which checks whether the username is available or not.

Now - if i trigger e.g. "handle password" and update the states password value, and I do this while the handle username function is still awaiting a response from the network request - as soon as the network request is done, i yield a state like

{...state, errors: { ...state.errors, username: error } }

Now, even though the state changed in between, this will set the password value back to the value it used to have before the handle username action was called.

If I use machine.state however it works well. Maybe adding a "getState()" function would be a viable addition for actions (if I didn't miss anything else here :))

Thanks in advance for your help - I really enjoy using stent with React!

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.