Frontend State Management (useListStore)
Relevant source files
The following files were used as context for generating this wiki page:The useListStore hook is the central state management solution for the Scripty frontend, built using the Zustand library. It is responsible for managing the application's core data, including the list of scripts (items), user-defined tags, and the UI state such as the currently selected item and active filters.
A key feature of this store is its persistence layer. It uses Zustand's persist middleware combined with a custom storage implementation that leverages the @tauri-apps/plugin-fs API. This ensures that the application state, specifically scripts and tags, is automatically saved to and hydrated from a local JSON file (scriptStorage.json) within the user's application data directory, providing a seamless experience across sessions.
Sources: src/Hooks/useListStore.js
Architecture and Persistence
The store's architecture is defined by Zustand's create function and enhanced by the persist middleware. The persistence mechanism is custom-built to interact with the local filesystem via Tauri's APIs.
Sources: src/Hooks/useListStore.js:26-69
Persistence Flow
The state is persisted to a file named scriptStorage.json. The fileStorage object provides the necessary getItem, setItem, and removeItem methods that the persist middleware calls. These methods use Tauri's readTextFile, writeTextFile, and exists functions to manage the JSON file in the path provided by appDataDir.
The following diagram illustrates the persistence flow:
Sources: src/Hooks/useListStore.js:12-24
Middleware Configuration
The persist middleware is configured to only save the items and tags slices of the state. UI-specific state like selectedItem and filterTag is intentionally excluded to ensure it remains transient and resets between application launches.
// src/Hooks/useListStore.js:62-69
{
name: "scriptStorage",
partialize: (state) => ({
items: state.items,
tags: state.tags,
}),
storage: createJSONStorage(() => fileStorage),
},
Sources: src/Hooks/useListStore.js:62-69
State Structure
The useListStore manages several distinct pieces of state that are crucial for the application's functionality.
| Property | Type | Description | Initial Value |
|---|---|---|---|
items | Array<Object> | An array of script objects. Each object contains id, title, content, tags, and date. | [] |
tags | Array<string> | An array of available tags for categorizing scripts. | ["Routine", "SYSTEM", "Check", "User", "Admin", "Archive"] |
selectedItem | Object or null | The script object that is currently selected by the user for viewing in the DetailView. | null |
filterTag | string or null | The tag currently used to filter the list of scripts. | null |
Sources: src/Hooks/useListStore.js:28-35
Actions and Selectors
The store exposes a set of actions to mutate the state and selectors to retrieve derived data.
Actions
| Action | Parameters | Description |
|---|---|---|
addItem | item | Adds a new script object to the items array. |
addTag | tag | Adds a new tag to the tags array if it doesn't already exist. |
removeItem | id | Removes a script from the items array by its id. |
selectItem | item | Sets the selectedItem to the provided script object. |
clearSelection | - | Resets selectedItem to null. |
setItems | items | Replaces the entire items array. (Not currently used by components). |
setFilterTag | tag | Sets the filterTag used for filtering the script list. |
Sources: src/Hooks/useListStore.js:37-59
Selectors
getFilteredItems()
This is the primary selector for retrieving the list of scripts to be displayed. Its logic is as follows:
- If
filterTagis "Archive", it returns only items that include the "Archive" tag. - If another
filterTagis set, it returns items that include that tag but do not include the "Archive" tag. - If
filterTagisnull, it returns all items that do not include the "Archive" tag.
This logic effectively treats "Archive" as a special category, separate from the main, filterable list.
Sources: src/Hooks/useListStore.js:61-73
Component Interaction
Various React components subscribe to the useListStore to access state and dispatch actions, creating a reactive UI.
The diagram below shows how key components interact with the store.
Usage Examples
- Adding an Item: The
Formcomponent callsaddItemupon successful form submission.
Sources: src/components/Form/Form.jsx:9, 50 - Adding a Tag: The
FormTagcomponent callsaddTagto add a new category.
Sources: src/components/Form/FormTag.jsx:5, 9 - Displaying Items: The
Listcomponent usesgetFilteredItemsto render the list of scripts andselectItemwhen a user clicks an item.
Sources: src/components/Form/List.jsx:29-32 - Viewing Details: The
DetailViewcomponent subscribes toselectedItemto display its content and callsremoveItemto delete it.
Sources: src/components/DetailView/DetailView.jsx:7, 8, 32 - Filtering: The main
Appcomponent provides UI to callsetFilterTag, which in turn causes theListcomponent to re-render with filtered data.
Sources: src/App.jsx:25