### Initialize and Manage Store with rx-tiny-flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Illustrates the setup and usage of the `Store` class from `rx-tiny-flux`. It covers initializing the store with an initial state, registering reducers and effects, dispatching actions to modify state and trigger side effects, and selecting/subscribing to state changes. Emphasizes the importance of unsubscribing to prevent memory leaks. ```javascript // Library imports import { Store } from 'rx-tiny-flux'; // Import all your application's reducers, effects, and actions import { counterReducer, logReducer } from './path/to/your/reducers'; import { incrementAsyncEffect } from './path/to/your/effects'; import { increment, incrementAsync } from './path/to/your/actions'; // 1. The Store can start with an empty state. const initialState = {}; // 2. Create a new Store instance const store = new Store(initialState); // 3. Register all reducers. The store will build its initial state from them. store.registerReducers(counterReducer, logReducer); // 4. Register all effects. store.registerEffects(incrementAsyncEffect); // 5. Dispatch actions to trigger state changes and side effects. console.log('Dispatching actions...'); store.dispatch(increment()); store.dispatch(increment()); store.dispatch(incrementAsync()); // Will trigger the effect // 6. Select and subscribe to state changes. // It's crucial to capture the subscription object so we can unsubscribe later. const counterSubscription = store.select(selectCounterValue).subscribe((value) => { console.log(`Counter value is now: ${value}`); }); // 7. Clean Up (Unsubscribe) // In any real application, you must unsubscribe to prevent memory leaks. // When the subscription is no longer needed (e.g., a component is destroyed), // call the .unsubscribe() method. counterSubscription.unsubscribe(); ``` -------------------------------- ### Propagate Actions Across Contexts in ZeppOS with rx-tiny-flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md This example demonstrates how to propagate actions between different component contexts (App/Page and Side Service) in ZeppOS using rx-tiny-flux. It shows how to initiate a request from the App, handle it in the Side Service, and then update the UI in the App upon completion, all while preserving the original component context. ```javascript // Import operators and factories import { createEffect, ofType, isApp, isSideService, propagateAction, map, tap } from 'rx-tiny-flux'; import { fetchData, fetchDataSuccess } from './actions'; // Your actions // 1. Effect on the App: When `fetchData` is dispatched, propagate it to the Side Service. const requestDataEffect = createEffect(actions => actions.pipe( ofType(fetchData), // Listen for the initial request isApp(), // Run only on the App/Page side propagateAction() // Send the action to the Side Service ), { dispatch: false }); // 2. Effect on the Side Service: When `fetchData` is received, perform a task and dispatch a result. const handleDataRequestEffect = createEffect(actions => actions.pipe( ofType(fetchData), // Listen for the propagated action isSideService(), // Run only on the Side Service // Perform async work... then map the result to a success action. // You can use the standard `map` operator. The context is handled automatically! map(() => fetchDataSuccess({ payload: 'data from service' })) )); // 3. Effect on the App: Listen for the final success action and use its context to update the UI. const showSuccessToastEffect = createEffect(actions => actions.pipe( ofType(fetchDataSuccess), isApp(), tap(action => { // This works because the `context` from the original `fetchData` action was // automatically attached to the `fetchDataSuccess` action by the store. if (action.context && action.context.toast) { action.context.toast.show({ text: 'Data loaded!' }); } }) ), { dispatch: false }); ``` -------------------------------- ### Show Toast Notification from rx-tiny-flux Effect Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md An example effect using `rx-tiny-flux` that listens for a specific action (`operationSuccess`) and, using the `context` injected into the action, triggers a toast notification via a `toast` plugin. This demonstrates accessing component context within effects. Dependencies include `rx-tiny-flux`. ```javascript // effects/toast.effect.js import { createEffect, ofType, tap } from 'rx-tiny-flux'; import { operationSuccess } from '../actions'; export const showSuccessToastEffect = createEffect( (actions$) => actions$.pipe( ofType(operationSuccess), // The action now contains the 'context' of the Page that dispatched it tap((action) => { // Check if the context and the toast plugin exist before using it if (action.context && action.context.toast) { action.context.toast.show({ text: 'Operation successful!' }); } }) ), // This effect does not dispatch a new action, so we set dispatch: false { dispatch: false } ); ``` -------------------------------- ### Access State in ZeppOS Effects with withLatestFromStore in rx-tiny-flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md This example demonstrates how to access the latest application state within an effect using the `withLatestFromStore` operator in rx-tiny-flux. This is particularly useful in ZeppOS where the store instance may not be directly available during effect definition. It shows how to combine an action with data selected from the store. ```javascript // Import all operators from the main entry point import { createEffect, ofType, withLatestFromStore, switchMap, map, catchError, from, of } from 'rx-tiny-flux'; import { fetchData, fetchDataSuccess, fetchDataError } from './actions'; import { selectCurrentUserId } from './selectors'; const fetchDataEffect = createEffect(actions => actions.pipe( ofType(fetchData), // Combines the action with the latest value from the store using the selector withLatestFromStore(selectCurrentUserId), // The next operator receives an array: [action, userId] switchMap(([action, userId]) => from(api.fetchDataForUser(userId)).pipe( map(data => fetchDataSuccess(data)), catchError(error => of(fetchDataError(error))) )) )); ``` -------------------------------- ### Create and Register rx-tiny-flux Store in App Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Demonstrates the creation of a rx-tiny-flux store instance, registration of reducers, and subsequent registration of the store plugin with `BaseApp`. This sets up the central store for your application. Dependencies include `@zeppos/zml` and `rx-tiny-flux`. ```javascript // app.js - Your application's entry point import { BaseApp } from '@zeppos/zml'; import { Store } from 'rx-tiny-flux'; import { storePlugin } from 'rx-tiny-flux'; // 1. Import your reducers, actions, etc. import { counterReducer } from './path/to/reducers'; // 2. Create your store instance const store = new Store({}); store.registerReducers(counterReducer); // 3. Register the plugin on BaseApp, providing the store. BaseApp.use(storePlugin, store); App(BaseApp({ // ... your App config })); ``` -------------------------------- ### Register rx-tiny-flux Plugin and Use in Page Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Shows how to register the `storePlugin` on `BasePage` without explicitly passing the store, as it's retrieved from the App. It also illustrates using `this.subscribe` to listen for state changes and `this.dispatch` to trigger actions within a page component. Dependencies include `@zeppos/zml` and `rx-tiny-flux`. ```javascript // page/index.js - An example page import { BasePage, ui } from '@zeppos/zml'; import { selectCounterValue } from '../path/to/selectors'; import { increment } from './path/to/actions'; // 4. Register the plugin on BasePage, without providing the store. It will be retrieved from the App. BasePage.use(storePlugin); Page(BasePage({ build() { const myText = ui.createWidget(ui.widget.TEXT, { /* ... */ }); // 5. Use `this.subscribe` to listen to state changes this.subscribe(selectCounterValue, (value) => { myText.setProperty(ui.prop.TEXT, `Counter: ${value}`); }); // Use `this.dispatch` to dispatch actions ui.createWidget(ui.widget.BUTTON, { // ... click_func: () => this.dispatch(increment()), }); }, onDestroy() { // No need to unsubscribe manually! // The storePlugin will do it for you automatically. console.log('Page destroyed, subscriptions cleaned up.'); } })); ``` -------------------------------- ### Create Actions with Rx-Tiny-Flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Demonstrates how to create action creators using the `createAction` factory function in Rx-Tiny-Flux. Actions are plain objects describing events, optionally with a payload. They are dispatched to trigger state changes in the store. ```javascript import { createAction } from 'rx-tiny-flux'; // An action creator for an event without a payload const increment = createAction('[Counter] Increment'); // An action creator for an event with a payload const add = createAction('[Counter] Add'); // Dispatching the actions store.dispatch(increment()); // { type: '[Counter] Increment' } store.dispatch(add(10)); // { type: '[Counter] Add', payload: 10 } ``` -------------------------------- ### Create Reducers with Rx-Tiny-Flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Illustrates the creation of reducers using `createReducer`, `on`, and `anyAction` helpers from Rx-Tiny-Flux. Reducers are pure functions that specify state changes in response to dispatched actions. They manage specific slices of the state and can optionally react to all actions. ```javascript // Library imports import { createReducer, on, anyAction } from 'rx-tiny-flux'; // Your application's action imports import { increment, decrement, incrementSuccess } from './actions'; // This reducer manages the 'counter' slice of the state. const counterReducer = createReducer( // 1. The jsonpath to the state slice '$.counter', // 2. The initial state for this slice { value: 0, lastUpdate: null }, // 3. Handlers for specific actions on(increment, incrementSuccess, (state) => ({ ...state, value: state.value + 1, lastUpdate: new Date().toISOString(), })), on(decrement, (state) => ({ ...state, value: state.value - 1, lastUpdate: new Date().toISOString(), })) ); // This reducer manages the 'log' slice and reacts to ANY action. const logReducer = createReducer( '$.log', [], // Initial state for this slice // Using the `anyAction` token to create a handler that catches all actions. on(anyAction, (state, action) => [...state, `Action: ${action.type} at ${new Date().toISOString()}`]) ); ``` -------------------------------- ### Create Feature and Derived Selectors with rx-tiny-flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Demonstrates using `createFeatureSelector` to select a top-level state slice via JSONPath and `createSelector` to compose selectors for derived data. Safely accesses nested properties using optional chaining. The selector is then used with the store to subscribe to state changes. ```javascript import { createFeatureSelector, createSelector } from 'rx-tiny-flux'; // 1. We use `createFeatureSelector` with a jsonpath expression to get a top-level slice of the state. const selectCounterSlice = createFeatureSelector('$.counter'); // 2. We use `createSelector` to compose and extract more granular data from the slice. const selectCounterValue = createSelector( selectCounterSlice, (counter) => counter?.value // Added 'optional chaining' for safety ); const selectLastUpdate = createSelector( selectCounterSlice, (counter) => counter?.lastUpdate ); // Using the selector with the store store.select(selectCounterValue).subscribe((value) => { console.log(`Counter value is now: ${value}`); }); ``` -------------------------------- ### Create Effects with Rx-Tiny-Flux Source: https://github.com/baumblatt/rx-tiny-flux/blob/main/Readme.md Shows how to build effects in Rx-Tiny-Flux using `createEffect` and RxJS operators like `ofType` and `concatMap`. Effects handle side effects, such as asynchronous operations, by listening to actions and potentially dispatching new actions. ```javascript // Core library imports import { createEffect, ofType, from, map, concatMap } from 'rx-tiny-flux'; // Your application's action imports import { incrementAsync, incrementSuccess } from './actions'; // A function that simulates an API call (e.g., fetch) which returns a Promise const fakeApiCall = () => new Promise(resolve => setTimeout(() => resolve({ success: true }), 1000)); const incrementAsyncEffect = createEffect((actions$) => actions$.pipe( // Listens only for the 'incrementAsync' action ofType(incrementAsync), // Use concatMap to handle the async operation. // It waits for the inner Observable (from the Promise) to complete. concatMap(() => from(fakeApiCall()).pipe( // `from` converts the Promise into an Observable map(() => incrementSuccess()) // On success, map the result to a new action ) ) ) ); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.