docs/development/state-management/state-management-selectors.mdx
Selectors are data retrieval modules under the LobeHub data flow development framework. Their role is to extract data from the store using specific business logic for consumption by components.
Taking src/store/tool/slices/plugin/selectors.ts as an example:
This TypeScript code snippet defines an object named pluginSelectors, which contains a series of selector functions used to retrieve data from the plugin storage state. Selectors are functions that extract and derive data from a zustand store. This specific example is for managing the state related to the frontend application's plugin system.
Here are some key points to note:
getCustomPluginById: Returns the custom plugin based on the plugin ID.getInstalledPluginById: Returns the installed plugin based on the plugin ID.getPluginMetaById: Returns the plugin metadata based on the plugin ID.getPluginSettingsById: Returns the plugin settings based on the plugin ID.getToolManifestById: Returns the plugin manifest based on the plugin ID.installedCustomPluginMetaList: Returns metadata for all installed custom plugins.installedPluginManifestList: Returns the manifests of all installed plugins.installedPluginMetaList: Returns a processed metadata list for all installed plugins.installedPlugins: Returns the list of all installed plugins.isPluginHasUI: Determines if the plugin has UI components based on the plugin ID.isPluginInstalled: Checks if the plugin with the given ID is installed.storeAndInstallPluginsIdList: Returns the identifiers of all installed plugins.Selectors are highly modular and maintainable. By encapsulating complex state selection logic in separate functions, they make the code more concise and intuitive when accessing state data in other parts of the application. Additionally, by using TypeScript, each function can have clear input and output types, which helps improve code reliability and development efficiency.
Taking the installedPluginMetaList method as an example, its code is as follows:
const installedPlugins = (s: ToolStoreState) => s.installedPlugins;
const installedPluginMetaList = (s: ToolStoreState) =>
installedPlugins(s)
// Filter out Composio plugins (they have their own display location)
.filter((p) => !p.customParams?.composio)
.filter((plugin) => isInstalledPluginAvailableInCurrentEnv(plugin))
.map<InstallPluginMeta>((p) => ({
author: p.manifest?.author,
createdAt: p.manifest?.createdAt,
homepage: p.manifest?.homepage,
identifier: p.identifier,
runtimeType: p.runtimeType,
type: p.source || p.type,
...getPluginMetaById(p.identifier)(s),
}));
installedPlugins selector: Used to retrieve the raw list of all installed plugins from the tool state storage ToolStoreState.installedPluginMetaList selector: Calls the installedPlugins selector, filters out Composio plugins and plugins unavailable in the current environment, and maps the remaining entries into the metadata shape consumed by the UI.In components, the final consumed data can be directly obtained by importing:
import { useToolStore } from '@/store/tool';
import { pluginSelectors } from '@/store/tool/selectors';
const Render = () => {
const list = useToolStore(pluginSelectors.installedPluginMetaList);
return <> ...
</>;
};
The benefits of implementing this approach are:
With this design, LobeHub developers can focus more on building the user interface and business logic without worrying about the details of data retrieval and processing. This pattern also provides better adaptability and scalability for potential future changes in state structure.