WebCell

WebCell v2 to v3 migration

WebCell v3 is heavily inspired by the Local Observable State idea of MobX, and not only React, Web Components can be much easier to manage the Inner State & Logic, without any complex things:

  1. State type declaration
  2. this.state declaration & its type annotation/assertion
  3. this.setState() method calling & its callback
  4. confusive Hooks API...

Just declare a State Store class as what the Global State Managment does, and initial it on the this (a Web Component instance). Then use the state, and observe them, as MobX's usual, everything is done.

import {
    component,
+   observer,
-   mixin,
-   createCell,
-   Fragment
} from 'web-cell';
+import { observable } from 'mobx';

-interface State {
+class State {
+   @observable
-   key: string;
+   accessor key = '';
}

@component({
    tagName: 'my-tag'
})
+@observer
-export class MyTag extends mixin<{}, State>() {
+export class MyTag extends HTMLElement {
-   state: Readonly = {
-       key: 'value'
-   };
+   state = new State();

-   render({}: any, { key }: State) {
+   render() {
+       const { key } = this.state;

        return <>{value};
    }
}

At the same time, shouldUpdate() {} life-cycle has been dropped. You just need to control the logic before states changed in your State class methods.

DOM properties aren't like React's props, they're reactive. They are not only responsible to update Component views, but also synchronize with HTML attriutes.

MobX's @observable & reaction() are awesome APIs to implement these above with clear codes, so we add mobx package as a dependency:

npm install mobx

On the other hand, mobx-web-cell adapter has been merged into the core package.

+import { JsxProps } from 'dom-renderer';
import {
-   WebCellProps,
    component,
    attribute,
-   watch,
+   observer,
-   mixin,
-   createCell,
-   Fragment
} from 'web-cell';
-import { observer } from 'mobx-web-cell';
+import { observable } from 'mobx';

-export interface MyTagProps extends WebCellProps {
+export interface MyTagProps extends JsxProps {
    count?: number
}

@component({
    tagName: 'my-tag'
})
@observer
-export class MyTag extends mixin() {
+export class MyTag extends HTMLElement {
+   declare props: MyTagProps;

    @attribute
-   @watch
+   @observable
-   count = 0;
+   accessor count = 0;

-   render({ count }: MyTagProps) {
+   render() {
+       const { count } = this;

        return <>{count};
    }
}
import {
    component,
-   mixin
} from 'web-cell';

@component({
    tagName: 'my-tag',
-   renderTarget: 'children'
})
-export class MyTag extends mixin() {
+export class MyTag extends HTMLElement {
}
import {
    component,
-   mixin
} from 'web-cell';

@component({
    tagName: 'my-tag',
-   renderTarget: 'shadowRoot'
+   mode: 'open'
})
-export class MyTag extends mixin() {
+export class MyTag extends HTMLElement {
}

This makes Shadow CSS to react with Observable Data updating.

+import { stringifyCSS } from 'web-utility';
import {
    component,
-   mixin
} from 'web-cell';

@component({
    tagName: 'my-tag',
-   renderTarget: 'shadowRoot',
+   mode: 'open',
-   style: {
-       ':host(.active)': {
-           color: 'red'
-       }
-   }
})
-export class MyTag extends mixin() {
+export class MyTag extends HTMLElement {
    render() {
        return <>
+           
            test
        ;
    }
}
  1. mixin() => HTMLElement & its Sub-classes
  2. mixinForm() => HTMLElement & @formField
  3. @watch => @observable accessor
  1. Legacy architecture
  2. Modern architecture
  3. MobX lite
MMNEPVFCICPMFPCPTTAAATR