GithubHelp home page GithubHelp logo

thepassle / atom Goto Github PK

View Code? Open in Web Editor NEW
17.0 17.0 1.0 1.28 MB

A flexible state manager

Home Page: https://klaxon-atom.netlify.app/

JavaScript 96.47% HTML 3.53%
lit-element lit-html state state-management webcomponents

atom's People

Contributors

thepassle avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

43081j

atom's Issues

Get rid of global map of atoms/selectors

It would be nice not to depend on a 'global' map of atoms/selectors.

I think this should be easily refactorable. Instead of having atoms return a {key: 'someAtom'}, we can just return the Atom instance. When initializing Selectors, we need to pass the Atom to the Selector anyway, so we can rely on that directly.

This might be a problem for the devtools though, since the global Map is required for getting the initial states of atoms/selectors, but we might be able to work around that.

selector that has depending selectors doesnt run its `get` if it was never connected to an element

If you have a Selector that was never registered to an element, that Selectors .active will be null

and even if other Selectors depend on that Selector, it will not execute, because it never was connected and is still null so the check to see if selector.active > 0 wont run the get function, because selector.active is null

maybe add a flag .hasSelectorDependencies on the selectors store? and add that to the check? then it will run

  • if you call getSelector that means the selector you're getting by definition has a dependency

    • but what if the depending selector is not active anymore? then the parent shouldnt run
  • Maybe when the current Selector is trying to get a parent value, it can avoid it when the current Selector self isnt active

  • Maybe the getSelector function should always call a parent Selectors get function? The downside of this is that it could lead to that Selectors get function to be called multiple times potentially. Maybe this is fine in case of calculations, but less so if a Selector does API calls.

I also dont think the docs about Selectors depending on inactive Selectors are correct. I think thats only correct if the selector ever WAS active (so its .active is 0 instead of null)

Possible feature: mobx-like magic

Mobx heavily uses "magic" (i.e. hides away most of the reactions/observations by default and 'figures them out').

Not everyone is a fan of this but it has proven to be fairly popular, so i had a go at doing similar with atom.

Here's what i have:

Usage

export class MyElement extends AtomLitElement {
  render() {
    return html`
      <button @click="${() => setCount(old => old - 1)}">-</button>
      <span>${count.getState()}</span>
      <button @click="${() => setCount(old => old + 1)}">+</button>
    `;
  }
}

Implementation

import {LitElement, html, PropertyValues} from 'lit-element';

// NOTE: atoms isn't currently exported
import {atom, atoms} from "@klaxon/atom";

const [count, setCount] = atom({
  key: 'count',
  default: 0
});

// Truly excellent name
class AtomicReactor {
  public callback: () => void;
  protected _accessed: Set<string> = new Set();

  public constructor(callback: () => void) {
    this.callback = callback;
  }

  public track(): () => void {
    const originalGet = atoms.get;

    // NOTE: overwriting a method like this always feels like hackery
    // but the only other way i suppose is to have atom itself have a concept
    // of notifying of accesses (e.g. an event fired when one is accessed, but more
    // performant than that).
    atoms.get = (key: string) => {
      this._accessed.add(key);
      return originalGet.call(atoms, key);
    };

    return () => {
      atoms.get = originalGet;

      for (const [key, atom] of atoms.entries()) {
        if (this._accessed.has(key)) {
          // NOTE: needs to be removed at some point so we don't fill
          // memory with event listeners over time
          atom.addEventListener(key, () => {
            this.callback();
          });
        }
      }
    };
  }
}

const reactor = Symbol();

class AtomLitElement extends LitElement {
  protected [reactor]?: AtomicReactor;

  public connectedCallback(): void {
    super.connectedCallback();

    this[reactor] = new AtomicReactor(() => {
      this.requestUpdate();
    });
  }

  public disconnectedCallback(): void {
    super.disconnectedCallback();

    // NOTE: probably needs a this[reactor].dispose() which
    // removes all those previously mentioned listeners
    this[reactor] = undefined;
  }

  protected update(change: PropertyValues): void {
    const reactorInstance = this[reactor];
    if (reactorInstance) {
      const disposer = reactorInstance.track();
      super.update(change);
      disposer();
    } else {
      super.update(change);
    }
   }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.