Skip to content

Core concepts

Genshi focuses on two major concepts:

  • Actions
  • Effects

Some other terminologies commonly used within these docs are:

  • State
  • Store
  • Dispatchers
  • Payloads

Most of these concepts are terms that you would be familiar with since they are common in state management libraries.

State

State is the data that your application needs to keep track of. It can be anything from a simple counter to a complex object with nested properties.

In Genshi, the state is immutable, which means that you cannot directly modify it. Instead, you create a new state object every time you want to update the state. You could mutate the state directly, but since Genshi is supposed to be used with a view library like React, Vue or Svelte, mutating the state directly could lead to unexpected behavior.

Store

The store is a bucket where your application state is stored. It is responsible for managing the state, and providing methods to update it.

In Genshi, the store is provides methods to define actions and effects, and to update the state. It also provides a way to subscribe to changes in the state, so that you can update your UI when the state changes.

Since Genshi is atomic and composable, you can create multiple stores in your application, and use them to manage different parts of your application state.

Here is an example of a store with a simple counter state:

import { Store } from "@genshi/core";
const store = new Store({
count: 0,
});

Actions

Actions are the primary way to update your application state in Genshi. They are synchronous functions that take the current state and return the new state.

Actions are pure functions, which means they do not have side-effects and always return the same output for the same input and are to be treated as such.

Here is an example of an action that increments the counter counter:

const increment = store.action("increment", (state) => ({
...state,
count: state.count + 1,
}));

Effects

Effects are the primary way to handle side-effects in Genshi. They are asynchronous functions that can dispatch actions, and perform other side-effects like API calls, logging and other asynchronous operations.

Effects are impure functions, which means they can have side-effects and are to be treated as such.

Here is an example of an effect that increments the counter every second:

const tick = store.effect("tick", ({ dispatch }) => {
setInterval(() => {
dispatch(increment);
}, 1000);
});

You can also make network requests in effects:

const fetchUser = store.effect("fetchUser", async ({ dispatch }) => {
const response = await fetch("https://api.example.com/server-counter");
const success = await response.json();
console.log("success:", success);
dispatch(increment);
});

Dispatcher

The dispatcher is a function that is used to dispatch actions and effects. It is provided by the store.

A dispatch is a way to send a message to the store, which then updates the state or performs an effect based on the type of message.

Here is an example of dispatching an action:

const store = new Store(0);
const increment = store.action("increment", (state) => state + 1);
store.dispatch(increment);

Payloads

Payloads are the arguments that you pass to actions and effects. They are used to pass data to the action or effect.

Here is an example of an action that takes a payload:

const setCount = store.action("setCount", (state, count) => ({
...state,
count,
}));