From f6c114057de236bc0a157aafbc0d4fd4006151c7 Mon Sep 17 00:00:00 2001 From: JuliusKoronciCH Date: Sun, 7 Apr 2024 17:30:13 +0200 Subject: [PATCH] update readme with throtle --- README.md | 221 +++--------------------------------------------------- 1 file changed, 9 insertions(+), 212 deletions(-) diff --git a/README.md b/README.md index 9ac19d4..f839a28 100644 --- a/README.md +++ b/README.md @@ -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) @@ -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 ( -
- setName(e.target.value)} /> - setCity(e.target.value)} /> -
- ); -} -``` - -## Why Dantian? - -```mermaid -flowchart LR - subgraph Initialization - InitState["Initial State"] --> CreateStore["createEventStore()
Dantian Event Store"] - end - - subgraph Hydration - HydrationSource["Hydration Source
(API, localStorage, etc.)"] --> |@@HYDRATED| CreateStore - end - - subgraph PropertyUpdate - PublishEvent["publish(type, payload)
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 @@ -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'); @@ -327,83 +201,6 @@ export const { ``` import { useStoreValue, useIsHydrated } from './store'; -function App() { - const isHydrated = useIsHydrated(); - - // ... other components - - return ( -
- {isHydrated ? ( - {/* Render your main application content here */} - ) : ( -
Loading application state...
- )} - - -
- ); -} - -``` - -### Profile form - -``` -import { useStoreValue, publish } from './store'; - -function ProfileForm() { - const [name, setName] = useStoreValue('profile.name'); - const [city, setCity] = useStoreValue('profile.city'); - - return ( -
- setName(e.target.value)} /> - setCity(e.target.value)} /> -
- ); -} -``` - -### 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(); @@ -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 }); ``` @@ -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. @@ -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>(eventType: K, throtle?: number)` +- `getPropertyObservable>(eventType: K, throttle?: number)` - Returns an RxJS Observable that emits values whenever the specified property in the store is updated. @@ -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$`