![PyPI Now Supports iOS and Android Wheels for Mobile Python Development](https://cdn.sanity.io/images/cgdhsj6q/production/96416c872705517a6a65ad9646ce3e7caef623a0-1024x1024.webp?w=400&fit=max&auto=format)
Security News
PyPI Now Supports iOS and Android Wheels for Mobile Python Development
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Status: Experimental
Part of a lesson on Continuous Integration for AngularFirebase.com
Why? Because the best code is the code you don't write. Convention over configuration.
What? LightState is a magic state container designed for optimal developer happiness.
LightState is not opinionated. You can have one global state or multiple smaller states.
npm i lightstate -s
LightState provides you with one thing - StatefulObject
.
// Define it
const state = new StatefulObject({ favorites: null });
// Slice it
const slice = state.at('favorites');
// Read it
slice.get$(); // as Rx Observable
slice.value; // as JS object
// Mutate it
slice.update({ beer: 'La Fin du Monde' });
Make sure to install Redux Dev Tools to watch your state magically manage itself.
Lightstate removes the mental boilerplate of redux by generating actions based on predictible conventions.
When you mutate the state, it creates an action based on the following convention (you can override this behavior).
name - optional name of the stateful object action - name of the action path - where the action occured in dot notation
[name] action@path
Synchronous mutations will look this this.
[userState] UPDATE@profile.displayName
[userState] CLEAR
Async operations have their own convention. (1) start (2) mutate (3) complete/cancel/err.
[userState] OBSERVABLE_START@reviews.phoenix
[userState] OBSERVABLE_UPDATE@reviews.phoenix
[userState] OBSERVABLE_COMPLETE@reviews.phoenix
You can can pass options as a second argument.
name
give your container a unique name for action creation (a random name is assigned by default).devTools
devtools config or false (enabled by default)logger
console log state changes (enabled by default)middleware
a function that can intercept state changes[key:string]
add your own options, then intercept them with middlewareconst opts = {
name: 'user',
devTools: false,
middleware: myMiddlewareFunction
}
const state = new StatefulObject( default, opts )
All selectors can return a plain object, or Observable
with a $
convention.
// From Root state
state.get('hello.world'); // JS Object
state.get$('hello.world'); // Rx Observable
// From Slice
const slice = state.at('hello.world');
slice.value; // JS Object
slice.get$(); // Rx Observable
See if a property exists
state.has('some.deeply.nested.array[23]');
// returns boolean
Perform advanced collection filtering when you have an array of objects.
state.where$('users', {
age: v => v > 21,
city: v => v === 'NYC'
});
// returns filtered Observable array
Set will override the entire object with new data.
state.set({ username: 'nash' });
Update will only mutate the specified values.
state.update({ age: 30 });
Modify deeply nested properties
state.updateAt('users.userABC.profile', { name: 'doug' });
state.setAt(...);
Also
state.clear(); // next state {}
state.reset(); // reset to initial state
In most cases, you will need a reference to a specific slice of the stateful object.
const beer = state.at('beers.budlight.platinum');
A slice is just a scoped reference to the parent object, allowing you to to make references to deeply nested paths in the state.
beer.update({ abv: 6.0 });
You should use the mutation API above most of the time, but sometimes you might want to dispatch and handle an action manually.
Dispatch allows you to pass an action name, payload, and handler function (similar to a reducer function), then you return the next state.
const handler = (state, payload) => {
return { ...state, username: payload };
};
state.dispatch('CHANGE_USERNAME', payload, handler);
Async state management is a challenge on the web. The tool can automatically subscribe to Observables and resolve Promises, then make updates with the resolved values. It also keeps track of all running subscriptions in the state object, so you can manage, cancel, and analyze streaming subscriptions
const observable = http.get(...);
this.state.async('tasks.items', observable);
// note that it also works with promises
The feed
method will subscribe to the Observable (or Promise), patch the emitted values to the state, and dispatch two actions:
OBSERVABLE_START@path
on subscribeOBSERVABLE_SET@path
update with emitted dataBonus features: If you feed multiple Observables to a path, it will automatically cancel previous requests. It will also let you know when your observable sends the complete signal.
OBSERVABLE_COMPLETE@path
on completeOBSERVABLE_CANCEL@path
if unsubscribed automaticallyYou can access all active subscriptions the stateful object with state.subs
Works great with realtime data feeds like Firebase.
You can dispatch arbitrary actions to signal the start of something async. This can be useful debugging or reacting to the action stream (see method 3).
this.state.signal('MAKE_GET_REQUEST');
http.get(url).pipe(tap(data => {
state.update(data)
})
.subscribe()
Inspired by NgRx Effects, you can listen to actions and react.
this.state.actions$
.ofType('[mystate] MY_ACTION')
.pipe(
tap(action => {
// do stuff
})
)
.subscribe();
You can intercept state changes with middleware. For example, this package uses middleware to implement a logger and Redux Devtools. Just return the next state.
const yourMiddleware = (current, next, action, opts) => {
console.log(current, next, action, opts);
next = { ...next, hello: 'middleware' };
return next;
};
You can pass middleware through options or by calling use
. Note: Only one middleware function is allowed per StatefulObject.
const state = new StatefulObject({ name: 'bubba' }, opts);
state.use(yourMiddleware);
If you have highly complex requirements, look into a fully integrated solution like NGXS or NgRX.
Global Store, Redux Pattern. If you want global store, create a service that instantiates a single StatefulObject
then pass it around with Angular's DI.
Smart parent, dumb children. It's common to make a parent component stateful, then pass the state context down via @Input()
. Don't be afraid to use multiple state containers. Each container gets a unique name and it's own instance in devtools.
Get Creative. This is not an opinionated library. Architect your own state management solution with this swiss army knife.
FAQs
reactive state container
The npm package lightstate receives a total of 2 weekly downloads. As such, lightstate popularity was classified as not popular.
We found that lightstate demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
PyPI now supports iOS and Android wheels, making it easier for Python developers to distribute mobile packages.
Security News
Create React App is officially deprecated due to React 19 issues and lack of maintenance—developers should switch to Vite or other modern alternatives.
Security News
Oracle seeks to dismiss fraud claims in the JavaScript trademark dispute, delaying the case and avoiding questions about its right to the name.