A simple, elegant state manager for JavaScript applications.
Understate is a lightweight state management library inspired by Redux, designed with functional programming principles. It provides a clean API for managing application state using pure functions (mutators) to transform state over time.
Key features:
- Simple API: Create state instances, apply mutations, and subscribe to changes
- Functional Design: Uses pure mutator functions and higher-order function patterns
- State Indexing: Track and retrieve historical state snapshots by ID
- Async Support: Built-in support for asynchronous state mutations
- Zero Dependencies: Lightweight with no external dependencies
- Framework Agnostic: Works with React, Vue, vanilla JS, Node.js, or any JavaScript environment
Install Understate via npm, yarn, or pnpm:
# Using npm
npm install understate
# Using yarn
yarn add understate
# Using pnpm
pnpm add understate- Node.js or a browser environment
- ECMAScript 6 (ES2015) or later
- No additional dependencies required
importUnderstatefrom'understate';// Create a new state instance with an initial valueconstcounter=newUnderstate({initial: 0});// Subscribe to state changescounter.subscribe(value=>{console.log('Counter:',value);});// Define mutator functionsconstincrement=x=>x+1;constdecrement=x=>x-1;constadd=amount=>x=>x+amount;// Update the statecounter.set(increment);// Logs: "Counter: 1"counter.set(add(5));// Logs: "Counter: 6"counter.set(decrement);// Logs: "Counter: 5"// Get the current statecounter.get().then(value=>console.log('Current:',value));// 5For more comprehensive examples showcasing all library features, see examples/comprehensive-demo.js.
importUnderstatefrom'understate';// Create async state instanceconstdataState=newUnderstate({initial: {data: null,loading: false,error: null},asynchronous: true});// Async mutator for fetching dataconstfetchUser=userId=>asyncstate=>{try{constresponse=awaitfetch(`/api/users/${userId}`);constuser=awaitresponse.json();return{ user,loading: false,error: null};}catch(error){return{user: null,loading: false,error: error.message};}};// Subscribe to state changesdataState.subscribe(state=>{if(state.loading)console.log('Loading...');elseif(state.error)console.error('Error:',state.error);elseif(state.user)console.log('User:',state.user);});// Fetch user datadataState.set(fetchUser(123));importUnderstatefrom'understate';// Create state with indexing enabledconststate=newUnderstate({initial: 0,index: true});consthistory=[];// Track state IDsstate.subscribe((value,id)=>{if(id){history.push(id);console.log(`State ${value} saved with ID: ${id}`);}});constincrement=x=>x+1;// Make changesstate.set(increment);// State 1 saved with ID: <id1>state.set(increment);// State 2 saved with ID: <id2>state.set(increment);// State 3 saved with ID: <id3>// Retrieve historical statestate.get(history[0]).then(value=>{console.log('First state:',value);// 1});importUnderstatefrom'understate';conststate=newUnderstate({initial: 0});constincrement=x=>x+1;// Create subscriptionconstsubscription=state.subscribe(value=>{console.log('Value:',value);});state.set(increment);// Logs: "Value: 1"state.set(increment);// Logs: "Value: 2"// Unsubscribesubscription.unsubscribe();state.set(increment);// Nothing loggedFor complete API documentation, examples, and advanced usage patterns, see the full documentation.
new Understate(config)- Create a new state instancestate.set(mutator, options)- Update state using a mutator functionstate.get(id)- Retrieve current or historical statestate.subscribe(callback)- Subscribe to state changessubscription.unsubscribe()- Cancel a subscriptionstate.id(shouldIndex)- Get the current state ID
Contributions are welcome! Please read our Contributing Guide for details on:
- Code of conduct
- Development workflow
- Testing requirements
- Pull request process
# Clone the repository
git clone https://github.com/johnhenry/understate.git
cd understate
# Install dependencies
npm install
# Run tests
npm testISC License - see LICENSE for details.
Made with ❤️ by John Henry