Performance-oriented and highly adaptable state manager for all types of JS applications: Node.js, Web Components, WASM, React, etc.
The most important requirements for state managers is:
- Automatic subscriptions - you don't need to care about dependencies or configure selectors to get reactive updates.
- Batch updates - you could call
setState
function multiple times for one or different states. It will run only one update - Computed values - recalculate functions only when one of dependency values has been changed.
- Optimized UI rendering - observers tracking system prevent multiple calls of functions during the rendering phase.
npm i @walksky/state
State provides a convenient way to organize values, computed values and setters. It returns an array with two values:
[getters, setters] - a functions for getting and setting values.
To get value from state you need to call a signal: state.value()
;
import { createState } from '@walksky/state'
const [state, setState] = createState({
apples: 1,
price: 100,
});
const MyComponent = () => <div>Apples: {state.apples}</div>
Under construction
If you are using UI library based on functional components, to make your component reactive, wrap it with the observe
function.
import { observe } from '@walksky/state';
const MyComponent = ({someProp}) => {
return <div>
Apples: {state.apples}
MyProps: {someProp}
</div>
}
export default observe(MyComponent);
If you need a classic state, you could create an instance of State.
import State from '@walksky/state'
const state = new State({apples: 0});
// define action
const increaseApples = () => state.setState({apples: state.getState().apples + 1})
// use in your component
const Fruits = () => <div>Total price is: {totalPrice()}</div>
const IncreaseButton = () => <button onClick={increaseApples}>Increase</button>
In most cases, subscribe are rarely needed. For example:
- Data logging
- Calling rendering function in Web Components or other solutions with custom rendering
state.subscribe(() => console.log('Vaue updated:', state.getState().apples));
All you need to do is subscribe in connectedCallback
in your lifecycle callbacks
// Create a class for the element
class MyCustomElement extends HTMLElement {
static observedAttributes = ["color", "size"];
connectedCallback() {
state.subscribe(this.render)
}
disconnectedCallback() {
state.unsubscribe(this.render)
}
}
customElements.define("my-custom-element", MyCustomElement);
If you write your business logic with Webassembly, all you need is write a bridge
#[wasm_bindgen(method)]
pub fn execute(cart_item: JsCartItem) {
let new_cart = // result of hard business logic
self.js_state.set_state(new_cart);
}
import State from '@walksky/state'
import { State as WasmStateInterface, AddToCart } from 'path_to_your_generated_wasm_typed_file';
const cartState = new State({cart: []});
// implementation of WASM interface
class StateAdapter extends WasmStateInterface {
getState = cartState.getState
setState = cartState.setState
}
// create instance of usecase
let addToCartUseCase = new AddToCartUseCase(stateAdaper);
// now Application state will be updaten on usecase execution
addToCartUseCase.execute(item);
👷 Under construction...