native-elegant-store
v1.0.0
Published
A lightweight, type-safe state management library for Vanilla JavaScript.
Readme
native-elegant-store
A lightweight, type-safe state management library for Vanilla JavaScript.
Installation
npm install native-elegant-storeUsage
import { createStateStore } from "native-elegant-store";
// Define your state type
interface MyState {
count: number;
message: string;
}
// Define your actions type
interface MyActions {
increment: (state: MyState, amount: number) => MyState;
setMessage: (state: MyState, newMessage: string) => MyState;
}
// Initial state
const initialState: MyState = { count: 0, message: "" };
// Actions object
const actions: MyActions = {
increment: (state, amount) => ({ ...state, count: state.count + amount }),
setMessage: (state, newMessage) => ({ ...state, message: newMessage }),
};
// Create the store with an optional initialization callback
const myStore = createStateStore(initialState, actions, (initialState) => {
console.log("Store initialized with:", initialState);
});
// Subscribe to state changes
const unsubscribe = myStore.subscribe((newState) => {
console.log("State updated:", newState);
});
// Access the current state
console.log("Current state:", myStore.getState());
// Update the state directly (using a new state object)
myStore.updateState({ count: 1, message: "Direct object update" });
// Update the state directly (using a function)
myStore.updateState((prevState) => ({
...prevState,
message: "Direct function update",
}));
// Use a bound action
myStore.actions.increment(5);
// Use another bound action
myStore.actions.setMessage("Hello native-elegant-store!");
// Unsubscribe from state changes
unsubscribe();
// Test that unsubscribe works (this should not log to the console)
myStore.actions.increment(10);API
createStateStore<T, S extends { [key: string]: (state: T, ...args: any[]) => T }>(initialValue: T, actions?: S, cb?: (initialState: T) => void)
Creates a new state store.
Type Parameters:
T: The type of the state.S: The type of the actions object.
Parameters:
initialValue: T: The initial value of the state.actions?: S: An optional object containing action creators. Each action creator is a function that takes the current state as the first argument and returns a new state.cb?: (initialState: T) => void: An optional callback function that is called with the initial state when the store is created.
Returns:
An object with the following properties:
getState(): T: Returns the current state.updateState(newState: T | ((prevState: T) => T)): void: Updates the state. Accepts either a new state object or a function that takes the previous state and returns a new state.subscribe(subscriber: (newState: T) => void): () => void: Subscribes a function to state changes. Returns an unsubscribe function.actions: { [K in keyof S]: (...args: Parameters<S[K]> extends [T, ...infer P] ? P : never) => void }: An object containing the bound action creators. Each bound action calls the corresponding action creator and updates the state.
Example Usage (Advanced)
Using with Complex State
interface User {
id: number;
name: string;
posts: string[];
}
interface AppState {
currentUser: User | null;
isLoading: boolean;
}
interface AppActions {
setCurrentUser: (state: AppState, user: User) => AppState;
setLoading: (state: AppState, isLoading: boolean) => AppState;
addPost: (state: AppState, post: string) => AppState;
}
const initialAppState: AppState = { currentUser: null, isLoading: false };
const appActions: AppActions = {
setCurrentUser: (state, user) => ({ ...state, currentUser: user }),
setLoading: (state, isLoading) => ({ ...state, isLoading }),
addPost: (state, post) => {
if (state.currentUser) {
return {
...state,
currentUser: {
...state.currentUser,
posts: [...state.currentUser.posts, post],
},
};
}
return state;
},
};
const appStore = createStateStore(initialAppState, appActions);
appStore.actions.setCurrentUser({ id: 1, name: "John Doe", posts: [] });
appStore.actions.addPost("My first post!");
console.log(appStore.getState());Features
- Type Safety: Built with TypeScript, providing strong type checking.
- Simple API: Easy to learn and use.
- Subscribable Pattern: Notifies subscribers of state changes.
- Bound Actions: Creates type-safe bound actions.
- Vanilla JavaScript: No dependencies, works in any JavaScript environment.
- Initialization Callback: Allows you to perform actions on initialization.
- Direct State Updates: Supports direct state updates using objects or functions.
Contributing
Contributions are welcome! Feel free to submit issues or pull requests.
License
This project is licensed under the MIT License.
