npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

gluang

v0.0.5

Published

Simple shared app state management for Quarkc

Downloads

10

Readme

Gluang

gluang (音同:gluon /ˈɡluː ɒn/ 格鲁昂)[物理学] 胶子。用于链接夸克形成强子,构成基本粒子。

It also can be used in Lit.

Simple shared app state management for Quarkc.

Gluang automatically re-renders your Quarkc components, when a shared app state variable they use changes. It's like Quarkc's properties, but then shared over multiple components.

Installation

npm install gluang

Basic idea

You keep your shared state in a Gluang derived class. This class contains stateVar variables that contain the state. This class can also contain helper functions that modify the state. Decorate your Quarkc classes with the connectStore() mixin. This makes your components automatically re-render whenever a stateVar they use changes.

Usage

1. Create a Gluang object:

// my-store.js

import { createGluang, stateVar } from 'gluang';

class MyState extends createGluang {
    static get stateVars() {
        return {
            counter: 0
        };
    }
}

export const myState = new MyState();

2. Make your component aware of your state:

By using the connectStore() mixin on your Quarkc component class and then just using the stateVar variables in your render method:

// my-components

import { QuarkElement, customElement } from "quarkc";
import { connectStore } from 'gluang';
import { myState } from './my-state.js';

@customElement({ tag: "my-component"})
class MyComponent extends connectStore(QuarkElement) {

    render() {
        return (
            <h1>Counter: {myState.counter}</h1>
            <button onClick={() => myState.counter++}></button>
        )
    }

}

The components that read myState.counter will automatically re-render when any (other) component updates it.

In more technical words:

A component using the connectStore() mixin will re-render when any stateVar - which it read in the last render cycle - changes.

Docs

For more information about how to use Gluang, check the

TODO: docs.

How does this work?

Basics

When you define a stateVar variable, Gluang will observe those variables whenever they're get or set. When using the connectStore() mixin on a component, during the render of that component, there is a recorder active that records any stateVar that is accessed during the render of that component. At the end of the render, the recorded stateVar variables are collected and whenever one of them changes, the component will be re-rendered. If the re-render uses different stateVar variables, they are again recorded and observed for possible rerenders.

Implementation details

To re-render the component, the connectStore() mixin calls Quarkc's this.update(). This will enqueue an update request for the component. The component will re-render at the end of the execution queue. this.update() can be called multiple times during a particular JavaScript event (like a click), and it will only update the component once, at the end of the execution queue. So it doesn't matter when it is called multiple times when multiple stateVar variables are changed during a JavaScript event. This is an optimization feature built-in in Quarkc. Quarkc uses this optimization for it's own properties. This optimization works in the same way for Gluang's stateVar variables.

Notes

You can create and use multiple Gluang classes at the same time.

It is even encouraged to keep things separate. You can of course have one big Gluang derived class which contains all global app state variables. But it is probably cleaner if you categorize it into multiple smaller Gluang derived classes. For example, you can put each state class in a separate file, collected in a state/ folder, and import them at the places you need.

You can nest states

If your state requires more hierarchy, you can also nest states. It doesn't matter to your components how your state is structured, as long as it uses the correct references to your stateVar variables. Refer to the [docs](TODO: #state-handling/nested-states/) for more information about nesting states.

Only new assigns trigger a re-render. Updating an object/array won't trigger a re-render.

Just like Quarkc's properties, only a new assign of the stateVar triggers a re-render. For example if you have a state like this:

MyState extends Gluang {
    @stateVar() myObj = {myKey: 'myValue'};
    @stateVar() myArray = ['one', 'two', 'three'];
}

Then this won't trigger a re-render:

myState = new MyState();
myState.myObj.mykey = 'newValue';
myState.myArray.push('four');

You'll instead need to assign a new object to the stateVar:

myState.myObj = {...myState.myObj, myKey: 'newValue'};
myState.myArray = [...myState.myArray, 'four'];

Watching for changes inside objects is very complex matter and would make Gluang way more complicated than desirable. If you are interested in this kind of thing, check out observable-slim.

Extra features

Custom stateVar variables

You can easily extend Gluang with a custom stateVar handler. An example of this is the [asyncStateVar](TODO: async-state-var), which is a stateVar variation that makes handling with asynchronous data easy. To make a custom stateVar yourself, create a class that extends from StateVar, exported by Gluang. [Check out the documentation on this.](TODO: #advanced-usage/state-var-handler/)

FAQ

Why should I use shared state for my components? Doesn't that oppose the concept of web components?

The big feature of web components is that they are encapsulated through the Shadow DOM. That means that their internal state isn't affected by state from the outside. And also that the component's internal state doesn't affect other elements on the page. This makes web components great for creating reusable elements. Reusable elements should have no side-effects, meaning that they shouldn't change state outside of themselves.

Reusable elements are great and we should use them a lot. When you're building a full application however, it is also desirable to have application-specific components that have application-specific side-effects. For example, changing the global app state. And it is of course desirable, that when this global app state changes, the components that use this global app state are synchronized with it.

And you can also have a reusable component that has several internal sub-components. They all might need to share some common internal state.

Gluang is created for these use cases, and is meant to make it as simple as possible for the developer.

Notes

Gluang is fork from lit-state and I rewrote it to work with Quarkc.

Changes in this fork
  • Renamed to Gluang - so you can use npx gluang directly.
  • Add this.update() in connectStore in order to it can work with quarkc.
  • Remove connectedCallback,disconnectedCallback function in observerState(connectStore), Because there is no these functions in Quarkc.
  • Renamed some functions' name. Also made some changes to the readme.