Proposal: useObjectStore Hook
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 84
- Forks
- 18
- Avg merge
- 3m
- Merged PRs (30d)
- 1
Description
Summary: A hook to simplify the creation and management of object dictionaries in LocalStorage, with a simple interface for CRUD operations. This would be useful for storing objects that populate List and Grid views, for example.
Details: This hook would create a LocalStorage entry containing a dictionary of objects as a JSON string, and it would provide easy access to methods for accessing, removing, and updating objects, as well as for performing object key migrations and batch-adding of new keys. A cached option could be provided.
Quite a few extensions store objects in this way and would benefit from a dedicated implementation, especially one that supports future development by providing methods for migrations (since the need/want to rename or delete keys is often unforeseen). Moreover, a standard implementation would allow additional features going forward, e.g. an option to use a JSON file in the extension's support directory rather than in LocalStorage, with minimal changes in extensions' code.
I'd be happy to work on this if there's support for it.
Proposed Interface:
interface LocalObjectStore<T> {
allObjects: () => T[];
// Add an object to the store, return the UUID for the object
addObject: (object: T) => string;
removeObject: (object: T) => void;
getObject: (id: string) => T | undefined;
setObject: (id: string, object: T) => void;
updateObject(id: string, updateFunction: (oldObject: T) => T): void;
removeObject: (id: string) => void;
clear: () => void;
// Rename a key within each object in the store, preserving the value
renameKey: (oldKey: string, newKey: string) => void;
// Add a key to each object in the store, using the provided function to generate the value
addKey: (key: string, valueFunction: (object: T) => any) => void;
// Delete a key from each object in the store
deleteKey: (key: string) => void;
}
Example:
import { Action, ActionPanel, Grid } from "@raycast/api";
import { useObjectStore } from '@raycast/utils';
interface EmojiItem {
name: string;
emoji: string;
description: string;
}
export default function Command() {
// Creates the store if it doesn't exist, or returns the existing store
const emojiStore = useObjectStore<EmojiItem>('emoji-items');
useEffect(() => {
emojiStore.addObject({
name: 'Smile',
emoji: '😀',
description: 'A happy face',
});
}, []);
// Loads items once upon first render, updates when items are added/removed/modified
const emojiItems = emojiStore.allObjects();
return(
<Grid>
{emojiItems.map((item) => (
<Grid.Item
key={item.id} // Auto-generated UUID
title={item.name}
subtitle={item.description}
content={item.emoji}
actions={
<ActionPanel>
<Action
title="Remove"
onAction={() => emojiStore.removeObject(item.id)}
/>
</ActionPanel>
}
/>
))}
</Grid>
);
}
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the proposed LocalObjectStore interface and the useObjectStore example in this issue. Resolve the CRUD and migration semantics, including the duplicate removeObject signatures and cached/storage options, then define tests for persistence and updates before considering the feature complete.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- frontend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100