> For the complete documentation index, see [llms.txt](https://thebuildex.gitbook.io/enoria/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://thebuildex.gitbook.io/enoria/state-management/stores.md).

# Stores

Sometimes you want to have a global state of your app, accross all your widgets. Although it is not recommended if you can use per-widget state management. In certain cases, like to know if the user is logged in or not, it becomes very useful.

### Creating a Store

A Store is basically an object that contains state variables and functions to update it.

Create a new ModuleScript, and import the base Store class:

```lua
local Store = require(game.ReplicatedStorage.Common.Enoria.packages.store.Store)

local MyStore = function()
    -- TODO
end

return MyStore
```

The module is basically a function that will return our store object. We now need to create a new store object:

```lua
local Store = require(game.ReplicatedStorage.Common.Enoria.packages.store.Store)

local MyStore = function()
    local store = Store.new({
        LoggedIn = false
    })

    return store
end

return MyStore
```

The Store constructor takes a dictionnary with state variables and their initial value. Then, you can add getters and setters:

```lua
local Store = require(game.ReplicatedStorage.Common.Enoria.packages.store.Store)

local MyStore = function()
    local store = Store.new({
        LoggedIn = false
    })

    store:AddGetter("getLoggedIn", function()
        return store.State.LoggedIn
    end)

    store:AddSetter("setLoggedIn", function(value)
        store.State.LoggedIn = value
    end)

    return store
end

return MyStore
```

Now, we have to create an action: something that will change a/multiple state variable(s) and rebuild the UI. It takes a dictonnary as parameter. In this example, we call a Remote Function to validate if the username and password are matching. If so, we call the setLoggedIn setter:

```lua
local Store = require(game.ReplicatedStorage.Common.Enoria.packages.store.Store)
local login = game.ReplicatedStorage.login

local MyStore = function()
    local store = Store.new({
        LoggedIn = false
    })

    store:AddGetter("getLoggedIn", function()
        return store.State.LoggedIn
    end)

    store:AddSetter("setLoggedIn", function(value)
        store.State.LoggedIn = value
    end)

    store:AddAction("login", function(args)
        local success = login:InvokeServer(args.username, args.password)

        if success then
            store.Setters.setLoggedIn(true)
        else
            store.Setters.setLoggedIn(false)
        end
    end)

    return store
end

return MyStore
```

We can now import it and tell Enoria to use it in our main client script:

```lua
-- ...
local myStore = require(script.Parent.MyStore)
-- ...
e:Use(myStore())
--...
```

We are not finished yet! The store needs to know which widget(s) does he need to update on certain actions.

In a custom widget, access the store object and call the Listen method on an action:

```lua
-- in your custom widget constructor :
self.Context.Uses.Store:Listen(self, "login") -- listen to the login action
```

This widget will now rebuild itself when login action is called. You can do that like so:

```lua
-- ... somewhere, in an event, in your build method ...
self.Context.Uses.Store:Commit("login", {username = "TheBuildex", password = "1234"})
```
