# Store by event scheme

### State

Event Scheme is a config there you pass for every event handlers by type.

First of all, let\`s create a State. For example, we have some items which we want to display in a window by pages.

```typescript
interface PagingModel {
    pages: number;
    currentPage: number;
    total: number;
}
// Be careful, use type, but not interface
// Typescript behaviour :(
type State = {
    items: Item[];
    pageSize: number;
    itemsOnDisplay: number;
    paging?: PagingModel;
}

const InitState: State = {
    items: [],
    pageSize: 5,
    itemsOnDisplay: 0,
    paging: {
        pages: 0,
        currentPage: 0,
        total: 0,
    }
}
```

After that we can design our Event Scheme. Let\`s begin from Event Scope - which Events do we need?

```typescript
enum Events {
    LoadItems = 'LoadItems',
    ItemsLoaded = 'ItemsLoaded',
    PageChanged = 'PageChanged',
}
```

It is not nessesary to use Enum, but it is good practice to keep strings in constants of enums to easily modify them. Now, prepare your handers.

### Handlers

```typescript
import { writeAs } from './helpers';

// Dispatch an Event contains Server Data
const loadItems: ActionFn<State, void> = () =>
    new FoxEvent(Events.ItemsLoaded, someService.loadItems());

// Write our data from server to State by key 'items'
const writeItems: ReducerFn<State, Item[]> = writeAs('items');

// Update paging model when items are loaded
const setPagingModel: ReducerFn<State, Item[]> = (
    items: Item[],
    state: State,
): Partial<State> => ({
    paging: {
        pages: Math.round(items.length / state.pageSize),
        currentPage: 1,
        total: items.length,
    },
})

// Update items for display when got they from server
const setDisplayingItems: ReducerFn<State, Item[]> = (
    items: Item[],
    state: State,
): Partial<State> => ({
    itemsOnDisplay: (items || state.items).slice(
        state.paging?.currentPage * state.pageSize - 1,
        state.pageSize,
    ),
})

// Handle changing of page number
const changePage: ActionFn<State, number> = (page: number, state: State) =>
    state.paging.pages >= page
        ? new FoxEvent(Events.PagingChanged, {
                ...state.paging,
                currentPage: page,
            })
        : new FoxEvent('Error', 'Page number is not correct');
    
// Using another reducer to update data when page is changed
const updateDisplayItemsOnPageChange: ReducerFn<State, PagingModel> =
    (paging: PagingModel, state: State) =>
        setDisplayingItems(state.items, state)

```

Now we have a few small functions that are our bricks to build full system.  Let\`s put them on their places!

### Event Scheme

```typescript

const EventScheme = {
    [Events.LoadItems]: createHandlers<State, void>({
        actions: [
            [loadItems],
        ],
    })(Events.LoadItems),
    [Events.ItemsLoaded]: createHandlers<State, Item[]>({
        // You can order reducers to control changes
        reducers: [
            [writeItems],
            [setPagingModel],
            [setDisplayingItems],
        ],
    })(Events.ItemsLoaded),
    // I separated handling event from user and updating data
    [Events.UpdatePage]: createHandlers<State, number>({
        actions: [[changePage]]
    })(Events.UpdatePage),
    [Events.PagingChanged]: createHandlers<State, PagingModel>({
        reducers: [
            [writeAs<State>('paging')],
            [updateDisplayItemsOnPageChange],
        ]
    })(Events.PagingChanged)
}

type EventSchemeType = typeof EventScheme

```

So, you can build your scheme from small bricks, take parts of scheme and put it in another files, you can reuse them. That's why a function `createHandlers` returns another function to get EventName. It is small overhead that allows us to create a pack of handlers and reuse it to a few events.

At the end, we need to create our store and use it.

```typescript
import { DefaultStoreOptions } from './core/options';

const store = new ProtoStore<State, EventSchemeType>(
    InitState,
    EventScheme,
    DefaultStoreOptions,
);

```

EventScheme gives us some features, for example - type checking of the payload when you are dispatching event

![Passing number as payload type for an Event](/files/yJh4KpLyZZIBVLtCKaM3)

![](/files/veU3wv0cm29WZUPJRCt0)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://angkira.gitbook.io/foxstore/using-store/store-by-event-scheme.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
