Counter Tutorial
In this guide, we’ll walk through the process of creating a simple Counter app.

Source Code
You can get the source code for counter app from here.
git clone https://github.com/almin/almin.git
cd almin/examples/counter
npm install
npm start
# manually open
open http://localhost:8080/
The purpose of counter
- Press a button and count up!
 
End.
📝 Notes: Recommendation
1 UseCase = 1 file
UseCase
We start implementing the UseCase.
- Press a button and count up!
 
Start to create IncrementalCounterUseCase class.
"use strict";
import {UseCase} from "almin"
export default class IncrementalCounterUseCase extends UseCase {
    // UseCase should implement #execute method
    execute() {
        // Write the UseCase code
    }
}
We want to update the counter app state when the IncrementalCounterUseCase is executed.
Simply, put the counter app state to a Store.
Store
Second, We create CounterStore class.
"use strict";
import {Store} from "almin";
export class CounterStore extends Store {
    constructor() {
        super();
        // receive event from UseCase, then update state
    }
    // return state object
    getState() {
        return {
            count: 0 
        }
    }
}
Almin's Store can receive the dispatched event from a UseCase.
💭 Image:
IncrementalCounterUseCasedispatches "increment" event.CounterStorereceives the dispatched "increment" event and updates own state.
This pattern is the same Flux architecture.

In flux:
- dispatch "increment" action via ActionCreator
 - Store receives "increment" action and updates own state
 
UseCase dispatch -> Store
Return to IncrementalCounterUseCase and add "dispatch increment event"
"use strict";
import { UseCase } from "almin";
export class IncrementalCounterUseCase extends UseCase {
    // IncrementalCounterUseCase dispatch "increment" ----> Store
    // UseCase should implement #execute method
    execute() {
        this.dispatch({
            type: "increment"
        });
    }
}
A class inherited UseCase has this.dispatch(payload) method.
payload object must have type property.
{
    "type": "type"
}
The above is a minimal payload object.
Of course, you can include other properties to the payload.
{
    "type": "show",
    "value": "value"
}
So, IncrementalCounterUseCase dispatches the "increment" payload.
UseCase -> Store received
Next, We want to add the feature that can receive the "increment" payload to CounterStore.
A class inherited Store can implement receivePayload method.
"use strict";
import { Store } from "almin";
export class CounterStore extends Store {
    constructor() {
        super();
        // initial state
        this.state = {
            count: 0
        };
    }
    // receive event from UseCase, then update state
    receivePayload(payload) {
        if(payload.type === "increment"){
            this.state.count++;
        }
    }
    // return the state
    getState() {
        return this.state;
    }
}
All that is updating CounterStore's state!
But, We can separate the state and CounterStore as files.
It means that we can create CounterState.
Store
- Observe dispatch events and update state
- Write state: 
receivePayload() - Read state: 
getState() 
 - Write state: 
 
State
- It is the state!
 
State
We have created CounterState.js.
CounterStates main purpose is
- receive "payload" and return state.
 
"use strict";
// reduce function
export class CounterState {
    /**
     * @param {Number} count
     */
    constructor({ count }) {
        this.count = count;
    }
    reduce(payload) {
        switch (payload.type) {
            // Increment Counter
            case "increment":
                return new CounterState({
                    count: this.count + 1
                });
            default:
                return this;
        }
    }
}
You may have seen the pattern. So, It is reducer in the Redux.
Store -> State: NewState
Finally, we have added some code to CounterStore
- Receive dispatched event, then update 
CounterState CounterStore#getStatereturns the instance ofCounterState
A class inherited Store has this.setState() method that update own state if needed.
"use strict";
import { Store } from "almin";
import { CounterState } from "./CounterState";
export class CounterStore extends Store {
    constructor() {
        super();
        // initial state
        this.state = new CounterState({
            count: 0
        });
    }
    // receive event from UseCase, then update state
    receivePayload(payload) {
        this.setState(this.state.reduce(payload));
    }
    // return own state
    getState() {
        return this.state;
    }
}
📝 Note: Testing
We can test the above classes independently.
View Integration
This example uses React.
index.js
We will create index.js that is the root of the application.
First, we create a Context object that is communicator between Store and UseCase.
import {Context, Dispatcher} from "almin";
import {CounterStore} from "./store/CounterStore";
// a single dispatcher
const dispatcher = new Dispatcher();
// initialize store
const counterStore = new CounterStore();
// create store group
const storeGroup = new StoreGroup({
    // stateName : store
    "counter": counterStore
});
// create context
const appContext = new Context({
    dispatcher,
    store: storeGroup
});
Second, We will pass the appContext to App component and render to DOM.
ReactDOM.render(<App appContext={appContext} />, document.getElementById("js-app"))
The following is the full code of index.js:
Source:
counter/src/index.js
"use strict";
import React from "react";
import ReactDOM from "react-dom";
import { Context, Dispatcher, StoreGroup } from "almin";
import App from "./component/App";
import { CounterStore } from "./store/CounterStore";
// a single dispatcher
const dispatcher = new Dispatcher();
// a single store
const counterStore = new CounterStore();
// create store group
const storeGroup = new StoreGroup({
    // stateName : store
    counter: counterStore
});
// create context
const appContext = new Context({
    dispatcher,
    store: storeGroup,
    options: {
        // Optional: https://almin.js.org/docs/tips/strict-mode.html
        strict: true
    }
});
ReactDOM.render(<App appContext={appContext} />, document.getElementById("js-app"));
App.js
We will create App.js that is the root of component aka. Container component.
It receives appContext from index.js and uses it.
Source:
counter/src/component/App.js
"use strict";
import React from "react";
import PropTypes from "prop-types";
import { Context } from "almin";
import { CounterState } from "../store/CounterState";
import { Counter } from "./Counter";
export default class App extends React.Component {
    constructor(props) {
        super(props);
        // set initial state
        this.state = props.appContext.getState();
    }
    componentDidMount() {
        const appContext = this.props.appContext;
        // update component's state with store's state when store is changed
        const onChangeHandler = () => {
            this.setState(appContext.getState());
        };
        this.unSubscribe = appContext.onChange(onChangeHandler);
    }
    componentWillUnmount() {
        if (typeof this.unSubscribe === "function") {
            this.unSubscribe();
        }
    }
    render() {
        /**
         * Where is "CounterState" come from?
         * It is a `key` of StoreGroup.
         *
         * ```
         * const storeGroup = new StoreGroup({
         *   "counter": counterStore
         * });
         * ```
         * @type {CounterState}
         */
        const counterState = this.state.counter;
        return <Counter counterState={counterState} appContext={this.props.appContext} />;
    }
}
App.propTypes = {
    appContext: PropTypes.instanceOf(Context).isRequired
};
App's state
Root Component has state that syncs to almin's state.
Focus on onChange:
// update component's state with store's state when store is changed
const onChangeHandler = () => {
    this.setState(appContext.getState());
};
appContext.onChange(onChangeHandler);
If CounterStore's state is changed(or emitChange()ed), call onChangeHandler.
onChangeHandler does update App component's state.
Counter component
Counter component receives counterState and appContext via this.props.
CounterComponent.propTypes = {
    appContext: React.PropTypes.instanceOf(Context).isRequired,
    counterState: React.PropTypes.instanceOf(CounterState).isRequired
};
Execute UseCase from View
We can execute IncrementalCounterUseCase when Counter's Increment button is clicked.
    incrementCounter() {
        // execute IncrementalCounterUseCase with new count value
        const context = this.props.appContext;
        context.useCase(new IncrementalCounterUseCase()).execute();
    }
Execute IncrementalCounterUseCase and work following:
- Execute 
IncrementalCounterUseCase CounterStoreis updated(create newCounterState)AppComponent's state is updated viaonChangeHandlerCounterreceives newCounterState, refresh view
Source:
counter/src/component/Counter.js
"use strict";
import React from "react";
import PropTypes from "prop-types";
import { IncrementalCounterUseCase } from "../usecase/IncrementalCounterUseCase";
import { Context } from "almin";
import { CounterState } from "../store/CounterState";
export class Counter extends React.Component {
    incrementCounter() {
        // execute IncrementalCounterUseCase with new count value
        const context = this.props.appContext;
        context.useCase(new IncrementalCounterUseCase()).execute();
    }
    render() {
        // execute UseCase ----> Store
        const counterState = this.props.counterState;
        return (
            <div>
                <button onClick={this.incrementCounter.bind(this)}>Increment Counter</button>
                <p>Count: {counterState.count}</p>
            </div>
        );
    }
}
Counter.propTypes = {
    appContext: PropTypes.instanceOf(Context).isRequired,
    counterState: PropTypes.instanceOf(CounterState).isRequired
};
End
We have created a simple counter app.
Writing the pattern in this guide is the same of Flux pattern.

Next: We learn domain model and CQRS pattern while creating TodoMVC app.