---
description: The best way to use Foxstore
---

# 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](https://3961113901-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MjzP8wFnTukVKDM57Rh%2Fuploads%2FzOEiAnRUQtAWQqfo2WFB%2Fimage.png?alt=media\&token=8e3396ac-63e8-4e37-ae5f-e03611714813)

![](https://3961113901-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MjzP8wFnTukVKDM57Rh%2Fuploads%2FRLRX6eTnxQPv0EyADVR9%2Fimage.png?alt=media\&token=6d6aa870-9f7f-4253-8b5d-54b0dcc5a346)
