Modules
Just like Vuex, Hana uses the single state tree pattern. This means that all of the state of your application is stored in a single object. This object is called the Store.
As your application grows, the Store can quickly get out of hand and become difficult to manage. To solve this problem, Hana allows you to split your Store into modules.
Modules are basically mini stores that belong to a specific part of your application. They have their own state and reducers, and can be used to organize your Store. You can also use modules to neatly separate the state of your application into different parts if the single state tree pattern does not work for you.
Defining a module
Contrary to the grandiose name, modules are just objects. They have the following properties:
state
: An object containing the initial state of the module.reducers
: An object containing the reducers of the module.
const itemStore = {
state: {
item: 'Initial value',
},
reducers: {
setItem: (state, payload) => ({ ...state, item: payload }),
},
};
Registering a module
You can register a module in the createStore()
function. The createStore()
has a modules
property that accepts an array of modules.
import { createStore } from '@hanabira/store';
import itemStore from './itemStore';
const store = createStore({
..., // Other config
modules: [itemStore],
});
The example above registers a module called itemStore
that has a state object with an item
property and a reducer called setItem
. This module can be used in any component using the useStore()
hook, but we will get to that later.
Naming your modules
When registering a module, you can specify a namespace
for it. This namespace will be used to access the module's state and reducers. If you do not specify a namespace, Hana will treat the state and reducers of the module as if they were registered in the root of the Store.
const itemStore = {
namespace: 'items',
state: {
item: 'Initial value',
},
reducers: {
setItem: (state, payload) => ({ ...state, item: payload }),
},
};
In the example above, we are creating the itemStore
module with the items
namespace. This means that the state of the module will be accessible in the Store using the items
property. The same goes for the reducers.
import { useStore } from '@hanabira/store';
const Component = () => {
const [item, setItem] = useStore('items.item');
return (
<div>
<p>{item}</p>
<button onClick={() => setItem('New value')}>Set item</button>
</div>
);
};
Using state from a module
As shown in the previous section, using state from a module is very similar to using state from the Store. The only difference is that you need to specify the name of the module when grabbing the state. This is done by passing the name of the module, a dot, and the name of the state property.
const [item, setItem] = useStore('items.item');
Note that if you do not specify a namespace for your module, you can skip the first part of the path.
const [item, setItem] = useStore('item');
Using reducers from a module
Using reducers from a module is also very similar to using reducers from the Store. The only difference is that you need to specify the name of the module when grabbing the reducer. This is done by passing the name of the module, a dot, and the name of the reducer.
import { useReducer } from '@hanabira/store';
const Component = () => {
const setItem = useReducer('items.setItem');
return (
<div>
<button onClick={() => setItem('New value')}>Set item</button>
</div>
);
};
In the example above, we are grabbing the setItem
reducer from the items
module. This is done by passing items.setItem
to the useReducer()
hook. The same can be done with any other Hana function that accepts a reducer.
Note that if you do not specify a namespace for your module, you can skip the first part of the path.
const setItem = useReducer('setItem');