-
Notifications
You must be signed in to change notification settings - Fork 1
/
property.js
84 lines (70 loc) · 2.89 KB
/
property.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import { html, render } from "https://unpkg.com/lit-html";
import { ref } from "https://unpkg.com/lit-html/directives/ref.js";
import { repeat } from "https://unpkg.com/lit-html/directives/repeat.js";
import { withHooks, useEffect, useMemoize, useProperties, useRef, useState } from "../wchooks.js";
function ExamplePropertyContainer() {
const childRef = useRef();
const [myProp, setMyProp] = useState([1, 2, 3, 4]);
// list memoize dependencies
const deps = [myProp];
// define the function that checks if the deps have changed
const areDepsEqual = ([myProp], [oldMyProp] = []) => myProp?.length === oldMyProp?.length;
// create a pair of function to modify myProp, and update them recreate them every time myProp changes
const { addMyPropItem, removeMyPropItem } = useMemoize(
// [!] notice that the dep array is spread as arguments of the memoize function
(myProp) => ({
// add (last element + 1) to the myProp list
addMyPropItem() {
const last = myProp[myProp.length - 1] ?? 0;
setMyProp([...myProp, last + 1]);
},
// remove last element from the myProp list
removeMyPropItem() {
setMyProp(myProp.slice(0, -1));
},
}),
deps,
areDepsEqual
);
function resetMyPropFromParent() {
childRef.value?.resetMyProp();
}
return html`
<fieldset>
<legend><b>useProperty / useMemoize</b></legend>
<button id="add" @click=${addMyPropItem}>Add</button>
<button id="remove" @click=${removeMyPropItem}>Remove</button>
<button id="reset" @click=${resetMyPropFromParent}>Reset child from parent</button>
<example-property
${ref(childRef)}
.myProp=${myProp}
.onChange=${(myProp) => setMyProp(myProp)}
></example-property>
<span>→ play with <code>window.exampleProperty.myProp</code> in the console</span>
</fieldset>
`;
}
function ExampleProperty() {
const props = useProperties({
// setup the "myProp" property of the custom element, you'll then be able to access it directly with element.myProp
// this is a default value, in this example the actual value will be controlled by the parent component above
myProp: [],
// default value for a callback method that will be passed by the parent
onChange() {},
// define a method bound to the element
resetMyProp() {
// inside methods, you can directly access the element with `this`
this.myProp = [];
this.onChange(this.myProp);
},
});
useEffect((element) => {
window.exampleProperty = element;
}, []);
return html`
<span id="list">= [${repeat(props.myProp, (value) => html`<b>${value}</b>, `)}*]</span>
<button id="reset" @click=${props.resetMyProp}>Reset child</button>
`;
}
customElements.define("example-property", withHooks(ExampleProperty, render));
customElements.define("example-property-container", withHooks(ExamplePropertyContainer, render));