zippy-store
Version:
A lightweight and versatile global state management solution designed for seamless integration in both JavaScript and React applications. Provides a simple and efficient way to manage shared state across components and even in non-React JavaScript environ
277 lines (210 loc) • 8.29 kB
Markdown
# zippy-store
[](https://badge.fury.io/js/zippy-store)
[](https://opensource.org/licenses/MIT)
**zippy-store** is a lightweight, flexible, and type-safe global shared state management library for React, React Native, and JavaScript applications. It provides a simple API to manage global shared state, subscribe to state changes, and dispatch actions. With built-in support for selector, it ensures optimal performance by preventing unnecessary re-renders. Additionally, it includes seamless persistence, ensuring state is retained across sessions.
---
## Features
- 🚀 **Lightweight**: Minimalistic API with zero dependencies.
- 🛠 **Type-Safe**: Built with TypeScript for better developer experience.
- 🎯 **Selector**: Extract specific parts of the state to avoid unnecessary re-renders.
- 🔄 **Reactive**: Automatically re-renders components when the state changes.
- 🧩 **Modular**: Create multiple stores for different parts of your application.
- 📦 **Persistence**: Built-in persistence support for JavaScript, React and React Native(AsyncStorage) apps.
- 🔗 **Shared State**: Share and sync state across multiple components seamlessly.
- 📊 **Global Access**: Access and update state globally from any component.
- 📤 **State Synchronization**: Ensure consistent data flow between different UI sections.
- ⚡️ **Async Support**: Handle asynchronous state updates effortlessly.
---
## Installation
You can install **zippy-store** via npm:
```bash
npm install zippy-store
```
or
```bash
yarn add zippy-store
```
## Usage
### Creating a Store in React and React Native
You can create a store using the `create` function and use it in components.
```ts
import { create } from "zippy-store";
const useCounterTimerStore = create("counterTimerStore", (set, get) => ({ //set for setting the state and get for getting the state
counter: 0,
timer: 60,
user: { name: "John Doe", age: 30 },
incrementCounter: () => set((state) => ({ counter: state.counter + 1 })), // return the new state in set function with callback
decrementTimer: () => {
const { timer } = get(); // get the current value of timer
return set({ timer: timer - 1 }); //can also pass object in set directly
},
}));
export default useCounterTimerStore;
```
#### Example 1: Using Full State
```tsx
import React from "react";
import useCounterTimerStore from "./useCounterTimerStore";
const Example_1 = () => {
const { counter, timer, dispatch } = useCounterTimerStore();
return (
<div>
<h4>Example_1</h4>
<h2>Counter Value : {counter}</h2>
<h2>Timer Value: {timer}</h2>
<div>
<button onClick={dispatch.incrementCounter}>Increment Counter</button>
<button style={{ marginLeft: 10 }} onClick={dispatch.decrementTimer}>
Decrement Timer
</button>
</div>
</div>
);
};
export default Example_1;
```
#### Example 2: Using Selector to Optimize Re-renders
```tsx
import React from "react";
import useCounterTimerStore from "./useCounterTimerStore";
const Example_2 = () => {
const { counter, user_name, dispatch } = useCounterTimerStore((state) => ({ counter: state.counter, user_name: state.user.name })); // using selector
return (
<div>
<h4>Example_2</h4>
<h2>User Name : {user_name}</h2>
<h2>Counter Value : {counter}</h2>
<div>
<button onClick={dispatch.incrementCounter}>Increment Counter</button>
<button style={{ marginLeft: 10 }} onClick={dispatch.decrementTimer}>
Decrement Timer
</button>
</div>
</div>
);
};
export default Example_2;
```
### Example 3: Sharing State Between Components
Multiple components can share the same store and stay in sync with state updates.
```tsx
import { create, store } from "zippy-store";
const useAuthStore = create("authStore", (set, get) => ({
isAuthenticated: false,
user: null,
login: (user) => set({ isAuthenticated: true, user }),
logout: () => set({ isAuthenticated: false, user: null }),
}));
import React from "react";
import useAuthStore from "./authStore"; // Assuming the store is in authStore.ts
const Header = () => {
const { isAuthenticated, user, dispatch } = useAuthStore();
return (
<header>
{isAuthenticated ? (
<div>
Welcome, {user?.name}!
<button onClick={dispatch.logout}>Logout</button>
</div>
) : (
<button onClick={() => dispatch.login({ name: "Test User", email: "test@example.com" })}>Login</button>
)}
</header>
);
};
const Profile = () => {
const { isAuthenticated, user } = useAuthStore();
return (
<div>
<h2>Profile</h2>
{isAuthenticated ? (
<p>Email: {user?.email}</p>
) : (
<p>Please login to view your profile.</p>
)}
</div>
);
};
```
### Example 4: Async Support
zippy-store supports asynchronous state updates in actions.
```tsx
import { create } from "zippy-store";
const useMoviesStore = create((set) => ({
data: {},
fetch: async () => {
const response = await someApiCall()
set({ data: respoonse.data })
},
}))
// or
const useMoviesStore = create((set) => ({
data: {},
fetch: () => {
set(async () => {
const response = await someApiCall()
return { data: respoonse.data }
})
},
}))
```
### Example 4: Persistence Support
zippy-store supports persistence for React and JavaScript apps (React Native is not supported yet).
```ts
import { create } from "zippy-store";
const usePersistentStore = create("persistentStore", (set, get) => ({
theme: "light",
setTheme: (theme: string) => set(() => ({ theme })),
}), true); // Enable persistence with true as the third parameter
```
### Creating a Store and using it directly in JavaScript, React and React Native apps
You can access the underlying store object for more advanced use cases and in non-React JavaScript environments(non React Components).
```ts
import { store } from 'zippy-store';
const { dispatch } = store.createStore('counterTimerStore', (set, get) => ({
counter: 0,
timer: 60,
user: { name: "John Doe", age: 30 },
incrementCounter: () => set((state) => ({ counter: state.counter + 1 })),
decrementTimer: () => set((state) => ({ timer: state.timer - 1 })),
}));
// Get the current state
const counterTimerState = store.getState('counterTimerStore');
// Subscribe to changes
const unsubscribe = store.subscribe('counterTimerStore', (newState) => {
console.log('Store updated:', newState);
});
// Update the state directly
dispatch.incrementCounter();
// or
const actions = store.getActions('counterTimerStore');
actions.incrementCounter();
// or
store.setState('counterTimerStore', (state) => ({ counter: state.counter + 1 }));
// Unsubscribe when done
unsubscribe();
```
## API
### `create(storeKey: string, stateAndActionsFn: (set, get) => State & Partial<Actions>, persist?: boolean): Hook`
Creates a new store for the given `storeKey`.
#### Arguments:
- `storeKey`: Unique identifier for the store.
- `stateAndActionsFn`: A function with the initial state and actions. `set` allows updating the state. `get` allows accessing the state.
- `persist`: Boolean flag to enable persistence (default: `false`).
##### Returns:
- A hook that can be used in React components to access the state and actions.
### `store`
The global store object with the following methods:
- `store.createStore(key: string, stateAndActionsFn: (setState) => State & Actions, persist?: boolean): State`.
Initializes the store with the given `key` and `stateAndActionsFn` and returns the dispatch object with actions.
- `store.getActions(key: string): Actions`
Returns the current actions of a given `storeKey`.
- `store.getState(key: string): State`
Returns the current state of a given `storeKey`.
- `store.setState(key: string, newStateCb: (state) => Partial<State>)`
Updates the state for a given `storeKey`.
- `store.subscribe(key: string, callback: (newState) => void): UnsubscribeFn`
Subscribes to state changes of a given `storeKey` and returns an unsubscribe function.
## License
MIT
***Powered by Harish Ponna @2025***