1.1.0 • Published 2 months ago

@spider-baby/mini-state v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

MiniState

A lightweight, reactive state management library for Angular applications that simplifies handling async operations.

npm version license Angular Compatibility

Overview

MiniState is a simple yet powerful state management solution for Angular applications, designed to handle:

  • Async operation states (loading, success, error)
  • Data fetching and updates
  • UI feedback (loading indicators, success/error messages)
  • Component-level state management without the complexity of global state libraries
  • Signal-based state management compatible with Angular's latest features

Perfect for when NgRx feels like overkill but you still want clean, reactive patterns for managing component state.

Installation

npm install @spider-baby/mini-state

Compatible with Angular 18 and 19.

Key Features

  • 🔄 Reactive Patterns: Built with RxJS and Angular Signals for seamless reactive architecture
  • 🎯 Focused Purpose: Handles async operation states with minimal boilerplate
  • 🧩 Modular Design: Core MiniState augmented by specialized extensions like MiniCrudState
  • 🔌 Simple Integration: Works with any service that returns Observables
  • 📊 Efficient State Tracking: Automatic handling of loading states, errors, and success messages
  • 🔗 Reactive Triggers: Auto-trigger operations from route params, signals, and other observables
  • 🧬 Combinable States: Easily combine multiple operations with MiniStateCombined and MiniStateUtility

Basic Usage

Simple Data Fetching

import { Component, inject, DestroyRef } from '@angular/core';
import { MiniStateBuilder } from '@spider-baby/mini-state';
import { UserService } from './user.service';

@Component({
  selector: 'app-user-list',
  template: `
    @if (loading()) {
      <div>Loading users...</div>
    }
    
    @if (errorMsg()) {
      <div>{{ errorMsg() }}</div>
    }
    
    @for (user of users(); track user.id) {
      <div>{{ user.name }}</div>
    }
    
    <button (click)="refresh()">Refresh</button>
  `
})
export class UserListComponent {
  private userService = inject(UserService);
  private destroyRef = inject(DestroyRef);
  
  private state = MiniStateBuilder.Create(
    () => this.userService.getAll(),
    this.destroyRef,
    []  // Optional initial value
  );
  
  // Expose signals to template
  protected users = this.state.data;
  protected loading = this.state.loading;
  protected errorMsg = this.state.errorMsg;
  
  constructor() {
    // Trigger data load when component initializes
    this.state.trigger();
  }
  
  protected refresh() {
    this.state.retrigger();
  }
}

With Input Parameters

private searchState = MiniStateBuilder.CreateWithInput(
  (term: string) => this.userService.search(term),
  this.destroyRef
);

// Trigger a search
this.searchState.trigger('search term');

Automatically React to Route Parameters

private userId$ = this.route.paramMap.pipe(
  map(params => params.get('id')),
  filter((id): id is string => !!id)
);

private userState = MiniStateBuilder.CreateWithObservableInput(
  this.userId$,
  (id: string) => this.userService.getById(id),
  this.destroyRef
);

Advanced Features

CRUD Operations with MiniCrudState

private userCrudState = MiniCrudState.Create(
  (filter: UserFilter) => this.userService.getAll(filter),
  this.destroyRef
)
.setAddState(
  (user: User) => this.userService.create(user),
  (user, result) => `User ${user.name} created successfully!`
)
.setUpdateState(
  (user: User) => this.userService.update(user),
  (user, result) => `User ${user.name} updated successfully!`
)
.setDeleteState(
  (user: User) => this.userService.delete(user.id),
  (user, result) => `User ${user.name} deleted successfully!`
);

// Use the state
userCrudState.trigger(new UserFilter()); // Get all users
userCrudState.triggerAdd(newUser);        // Create user
userCrudState.triggerUpdate(updatedUser); // Update user
userCrudState.triggerDelete(userToDelete); // Delete user

Combining Multiple States

import { MiniStateCombined } from '@spider-baby/mini-state/utils';

// Create individual states
const getAllState = MiniStateBuilder.Create(
  () => this.userService.getAll(),
  this.destroyRef
);
const updateState = MiniStateBuilder.CreateWithInput(
  (user: User) => this.userService.update(user),
  this.destroyRef
);

// Combine for unified loading/error handling
const combinedState = MiniStateCombined.Combine(
  getAllState,
  updateState
);

// In template
@if (combinedState.loading()) {
  <loading-indicator/>
}

@if (combinedState.errorMsg()) {
  <error-message>{{ combinedState.errorMsg() }}</error-message>
}

Using MiniStateUtility for Complex State Combinations

import { MiniStateUtility } from '@spider-baby/mini-state/utils';

// Combine loading states from multiple state instances
const isLoading = MiniStateUtility.combineLoading(state1, state2, state3);

// Combine error messages
const combinedErrorMsgs = MiniStateUtility.combineErrorMsgs(state1, state2, state3);

// Combine data
const combinedData = MiniStateUtility.combineData(state1, state2, state3);

// Use in template
@if (isLoading()) {
  <loading-spinner/>
}

@if (combinedErrorMsgs()) {
  <error-alert>{{ combinedErrorMsgs() }}</error-alert>
}

API Documentation

Core Classes

  • MiniState: Base class that manages state for an async operation
  • MiniStateBuilder: Factory for creating MiniState instances with different configurations
  • MiniCrudState: Extended MiniState for CRUD operations
  • MiniStateCombined: Combines multiple MiniState instances for unified state management
  • MiniStateUtility: Utility class with static methods for combining state properties

MiniState Methods

  • trigger(input): Starts the async operation with the given input
  • retrigger(): Repeats the last operation with the same input
  • setSuccessMsgFn(): Sets a function to generate success messages
  • setOnSuccessFn(): Sets a function to execute after successful operations
  • setErrorMsgFn(): Sets a function to generate error messages
  • setOnErrorFn(): Sets a function to execute when errors occur
  • resetMessagesAndLoading(): Manually clears all messages and resets loading state

MiniStateUtility Methods

  • combineErrors: Combines error objects from multiple states
  • combineErrorMsgs: Combines error messages from multiple states
  • combineSuccessMsgs: Combines success messages from multiple states
  • combineLoading: Combines loading states from multiple states
  • combineData: Combines data from multiple states

Packages

  • @spider-baby/mini-state: Core library with MiniState, MiniStateBuilder, and MiniCrudState
  • @spider-baby/mini-state/utils: Utilities for combining and aggregating multiple state instances

Changes

CHANGELOG.md

License

MIT