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:
- State type declaration
this.state
declaration & its type annotation/assertionthis.setState()
method calling & its callback- 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<State> = {
- 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<HTMLElement> {
count?: number
}
@component({
tagName: 'my-tag'
})
@observer
-export class MyTag extends mixin<MyTagProps>() {
+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 <>
+ <style>
+ {stringifyCSS({
+ ':host(.active)': {
+ color: 'red'
+ }
+ })}
+ </style>
test
</>;
}
}
mixin()
=>HTMLElement
& its Sub-classesmixinForm()
=>HTMLElement
&@formField
@watch
=>@observable accessor