Actions

Introduction

Actions build up the API that will shape how to interact with your Conan State.

Actions & Reducers are concepts strongly interlinked with each other, we would strongly recommend to be familiar with the general concepts as for most use cases you won't need to create custom actions.

ConanJs provides automatically with an action for each reducer, and two out of the box actions update and updateAsap to deal with sync and async updates (explained in further detail later)

Actions are defined when creating state via a function that

  • Receives a thread to allow you accessing the reducers and other useful resources to describe your actions

A Thread is like a Conan State half baked, it has all you need to add additional logic to your actions, like the getData method, the monitor and the reducers already defined. Everything available from a thread is documented in the API

  • Returns the actual actions.

Imagine that you want to add an async action in your Conan State using the monitor, this could retrieve an authentication token and then you want to set the property of your state authenticated to the response

thread => ({
    authenticate(authenticationUrl) {
        return thread.monitor(
            Asaps.fetch (authenticationUrl),
            (response, reducers)=> reducers.$update(current=>({
                ...current,
                authenticated: response.authenticated
            }))
        );
    },
})

Note that this action is handling async operation with the monitor, which is further explained below.

The Actions Interface

Following the same principles as to the reducers interface, having the Actions described as a function that takes a thread and returns the actual Actions was also a meditated decision.

The result of this is that you can define a clear business interface that describes the actions that can be performed against your state, so a little bit of boiler plate upfront saves a lot of boilerplate down the line.

You can access all the actions through the 'do' property of your Conan State

stockPrices$.do.refresh();
shoppingBasket$.do.addItem(itemToAdd);

Chaining Actions

Another property of an action in ConanJs is that they are chainable, they return an ASAP of the state this action is going to generate.

Note that this is the case no matter if doing async or sync operations (as long as you use the monitor or other async techniques, like auto-binding)

This helps solving complex logic, for instance

stockOrders$.do.increaseBuyingLimitBy(1000).then(newLimit=>
    stockMarket$.do.getPriceFor('AAPL').then (applPrice=>
        stockOrders$.do.tryToBuy ('AAPL', applPrice / newLimit)
    )
);

Typescript users should note that they are likely going to have to create two interfaces one for the Reducers and for the Actions.

The default actions

Each Conan State alway has two actions:

  • update For sync updated

  • updateAsap For async updates

update is the counter part of the default reducer $update

updateAsap uses a monitor and the default reducer $update to let you update the Conan State async

For an example that uses a the default actions, check Hello Wow!

Reducer actions

This are generated automatically by the framework for each reducer, the generated actions will have

  • The same name as the reducer but dropping the initial '$'

  • Will return an ASAP of the state that this action will generate

For an example that uses reducer actions, check Todos

Auto-bind actions

This is the simplest way to generate asynchronous actions, it works by name convention. It will match your provided actions and the already existing reducers following this rules

  • It will find you actions which name matches the underlying reducer

  • It will assume that the matching provided action returns an ASAP that needs to be resolved for the state to change.

  • It will create a monitor on that ASAP and will pass the resulting value to the reducer which this action matches its name into.

For an example that uses auto bind, check Todos - Async

Monitor actions

If auto-bind is not an option, you can use a monitor (monitors are further explained in the async section)

For an example that uses monitor actions, check Github issues viewer

Custom actions

You can also create your completely custom actions if none of the previous options work for you.

Last updated