Skip to content

Commit

Permalink
update readme with throtle
Browse files Browse the repository at this point in the history
  • Loading branch information
JuliusKoronciCH committed Apr 7, 2024
1 parent 64a1ec0 commit f6c1140
Showing 1 changed file with 9 additions and 212 deletions.
221 changes: 9 additions & 212 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# Dantian - Event-Based State Management
# Dantian - Event-Based State Management

[![npm version](https://badge.fury.io/js/dantian.svg)](https://badge.fury.io/js/dantian)

Expand Down Expand Up @@ -95,99 +94,6 @@ In a landscape filled with state management solutions, event-based state managem

This readme aims to shed light on the benefits of event-based state management in React applications, highlighting its advantages over traditional approaches and offering insights into its potential impact on application development. By embracing event sourcing, developers can unlock new possibilities and overcome the limitations of existing state management solutions.

## Installation
Dantian is an event-based state management library designed specifically for React applications. By embracing an event-driven architecture, Dantian offers a fresh approach to managing application state, providing developers with flexibility, efficiency, and simplicity.

```
import { useStoreValue } from './store';
function ProfileForm() {
const [name, setName] = useStoreValue('profile.name');
const [city, setCity] = useStoreValue('profile.city');
return (
<form>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
<input type="text" value={city} onChange={(e) => setCity(e.target.value)} />
</form>
);
}
```

## Why Dantian?

```mermaid
flowchart LR
subgraph Initialization
InitState["Initial State"] --> CreateStore["createEventStore() <br/> Dantian Event Store"]
end
subgraph Hydration
HydrationSource["Hydration Source <br/> (API, localStorage, etc.)"] --> |@@HYDRATED| CreateStore
end
subgraph PropertyUpdate
PublishEvent["publish(type, payload) <br/> Publish Event"] --> |type| CreateStore
CreateStore --> |type| SubscribedComponents["Subscribed Components"]
SubscribedComponents --> StateUpdate["Component State Update"]
StateUpdate --> UI["UI Update"]
end
```

### Efficient Updates

Dantian leverages events as triggers for state updates, ensuring that only components subscribed to relevant events are re-rendered. This approach minimizes unnecessary re-renders and improves overall performance, especially in applications with complex state interactions.

### Flexibility

With Dantian, developers have complete control over how state updates are handled. There's no need to adhere to predefined structures or patterns imposed by a library. Instead, developers can define their own logic and workflows tailored to their specific needs, empowering them to build React applications that are both powerful and flexible.

### Simplicity

By embracing a declarative and functional approach, Dantian simplifies state management logic. Developers can focus on defining pure functions and utilities to handle state updates, leading to cleaner, more maintainable code. With Dantian, state management becomes intuitive and straightforward, even for complex applications.

## Key Features

- **Event-Based Architecture**: Dantian relies on events to trigger state updates, providing a clear and efficient mechanism for managing application state.
- **Fine-Grained Control**: Developers can subscribe to specific events and define custom logic for handling state updates, giving them precise control over how their applications behave.
- **Optimized Performance**: By minimizing unnecessary re-renders and focusing on efficient updates, Dantian ensures optimal performance even in large-scale applications with complex state interactions.
- **Simplified Development**: With its intuitive API and focus on simplicity, Dantian makes state management easy and accessible for developers of all skill levels, reducing the learning curve and speeding up development time.

## The React Landscape

In the realm of React state management, various solutions like Zustand, Redux, and even React's built-in `useState` and `useReducer` hooks have become popular choices. However, they each come with their own set of trade-offs and considerations.

### Zustand and Redux

Zustand and Redux are excellent choices for managing global state in React applications. They offer centralized stores, actions, and reducers, making it easier to manage complex state interactions. However, they can sometimes introduce unnecessary boilerplate and complexity, especially for smaller applications or simple state management needs.

### useState and useReducer

On the other end of the spectrum, React's built-in `useState` and `useReducer` hooks provide a lightweight and straightforward way to manage local component state. They are perfect for managing state within individual components or handling simple UI interactions. However, they lack built-in mechanisms for managing global state or handling complex state interactions across multiple components.

## The Downside of Traditional Approaches

While these solutions have their merits, they often suffer from one common issue: excessive re-renders. Whether it's due to shallow comparisons, unnecessary updates, or complex state management logic, the result is the same: decreased performance and potential UI glitches.

## The Promise of Event Sourcing

Event-based state management offers a compelling alternative. By decoupling state updates from the underlying logic and relying solely on events to trigger updates, it provides a more predictable and efficient way to manage state.

### Benefits of Event Sourcing

- **Efficient Updates:** Events provide a clear trigger for state updates, ensuring that only the components subscribed to relevant events are re-rendered. This minimizes unnecessary re-renders and improves overall performance.
- **Flexibility:** With event sourcing, developers have complete control over how state updates are handled. There's no need to adhere to predefined structures or patterns imposed by a library. Instead, developers can define their own logic and workflows tailored to their specific needs.
- **Simplicity:** By embracing a more declarative and functional approach, event-based state management simplifies state management logic. Developers can focus on defining pure functions and utilities to handle state updates, leading to cleaner and more maintainable code.

## Conclusion

In a landscape filled with state management solutions, event-based state management offers a refreshing alternative. By prioritizing efficiency, flexibility, and simplicity, it empowers developers to build React applications that are performant, scalable, and easy to maintain.

---

This readme aims to shed light on the benefits of event-based state management in React applications, highlighting its advantages over traditional approaches and offering insights into its potential impact on application development. By embracing event sourcing, developers can unlock new possibilities and overcome the limitations of existing state management solutions.

## Installation

```bash
Expand Down Expand Up @@ -224,38 +130,6 @@ export const {
// counter.tsx
import { useStoreValue, publish } from './store';
function Counter() {
const [count, setCount] = useStoreValue('count');
## Basic example
```
// store.ts
import { createEventStore } from 'dantian';

export const {
state$,
useStoreValue,
useHydrateStore,
useIsHydrated,
getPropertyObservable,
globalEventStore$,
publish,
systemEvents$,
} = createEventStore({
count: 0,
profile: { name: '', city: '' },
data: null,
isLoading: false
});

```
### Basic counter
```
// counter.tsx
import { useStoreValue, publish } from './store';

function Counter() {
const [count, setCount] = useStoreValue('count');
Expand Down Expand Up @@ -327,83 +201,6 @@ export const {
```
import { useStoreValue, useIsHydrated } from './store';
function App() {
const isHydrated = useIsHydrated();

// ... other components

return (
<div>
{isHydrated ? (
{/* Render your main application content here */}
) : (
<div>Loading application state...</div>
)}
<button onClick={() => setCount(count + 1)}>Increment</button>
<button onClick={() => setCount(count - 1)}>Decrement</button>
</div>
);
}

```
### Profile form
```
import { useStoreValue, publish } from './store';

function ProfileForm() {
const [name, setName] = useStoreValue('profile.name');
const [city, setCity] = useStoreValue('profile.city');

return (
<form>
<input type="text" value={name} onChange={(e) => setName(e.target.value)} />
<input type="text" value={city} onChange={(e) => setCity(e.target.value)} />
</form>
);
}
```
### Hydration at store creation
```
import { createEventStore } from 'dantian';

export const {
useStoreValue,
useHydrateStore,
useIsHydrated,
publish,
systemEvents$,
} = createEventStore({
// Initial state ...
}, {
hydrator: async () => {
// Check if we have saved state in localStorage
const storedState = localStorage.getItem('dantianState');
if (storedState) {
return JSON.parse(storedState);
}

// If no localStorage state, perhaps load defaults or fetch from API:
// return await fetch('/api/initial-state').then(res => res.json());
},
persist: (state) => {
try {
localStorage.setItem('dantianState', JSON.stringify(state));
} catch (error) {
// Handle potential errors during state saving
console.error('Failed to persist state', error);
}
}
});

```
```
import { useStoreValue, useIsHydrated } from './store';

function App() {
const isHydrated = useIsHydrated();
Expand Down Expand Up @@ -577,8 +374,8 @@ const [count, setCount] = useStoreValue('count');
// Access a property and disable caching
const [profileName, setProfileName] = useStoreValue('profile.name', { disableCache: true });
// Emit updates every 300ms to avoid too many rerenders
const [email, setEmail] = useStoreValue('profile.email', { throttle: 300 });
// Access a property and set frequency of updates
const [profileEmail, setProfileEmail] = useStoreValue('profile.email', { throttle: 100 });
```

Expand All @@ -600,7 +397,7 @@ MIT
- Parameters:
- `initialState`: The initial state object of your store.
- `options`: An optional object containing configuration settings:
- `debug`: Enables debug logging (default: `false`).
- `debug`: Enables debug logging (default: `false`).
- `hydrator`: An asynchronous function returning a promise resolving to the hydration data.
- `persist`: An asynchronous function to handle state persistence.

Expand All @@ -611,7 +408,7 @@ MIT
- `type`: The property path within the store to be updated (e.g., 'count', 'profile.name').
- `payload`: The new value for the specified property.

- `getPropertyObservable<K extends PropertyPath<T>>(eventType: K, throtle?: number)`
- `getPropertyObservable<K extends PropertyPath<T>>(eventType: K, throttle?: number)`

- Returns an RxJS Observable that emits values whenever the specified property in the store is updated.

Expand All @@ -628,21 +425,21 @@ MIT
- React hook to access and update a specific property within the store.
- Parameters:
- `type`: The property path within the store.
- `options.disableCache`:  property to control local caching behavior.
- `options.throtle`: property to control frequency of updates.
- Returns: An array containing:
- `options.disableCache`: boolean property to control local caching behavior.
- `options.throtle`: numeric property to control frequency of updates in ms.
- Returns: An array containing:
- The current value of the property.
- A function to update the property.

- `useHydrateStore()`

- React hook to trigger store hydration.
- Returns: A function to initialize the store with hydrated data.
- Returns: A function to initialize the store with hydrated data.

- `useIsHydrated()`

- React hook to determine if the store is hydrated.
- Returns: A boolean indicating hydration status.
- Returns: A boolean indicating hydration status.

- `systemEvents$`

Expand Down

0 comments on commit f6c1140

Please sign in to comment.