fix(lit-renderer): certain reactive props not init correctly (#1874)

* fix(lit-renderer): reactive props not init correctly

* test(renderer-lit): implement testing suggestiosn

* chore(renderer-lit): upload changeset

* fix(renderer-lit): call connCallback on server

* fix(renderer-lit): do not set reserved JSX props

* fix(renderer-lit): do not check for reserved attributes

Co-authored-by: Nate Moore <nate@skypack.dev>
This commit is contained in:
Elliott Marquez 2021-11-22 13:01:32 -08:00 committed by GitHub
parent c22e4c69ec
commit ec01d1b43f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 56 additions and 3 deletions

View file

@ -0,0 +1,5 @@
---
'@astrojs/renderer-lit': patch
---
renderer-lit will bind to properties rather than attributes fixing certain binding issues

View file

@ -3,9 +3,26 @@ import { LitElement, html } from 'lit';
export const tagName = 'my-element';
export class MyElement extends LitElement {
static properties = {
bool: {type: Boolean},
str: {type: String, attribute: 'str-attr'},
obj: {type: Object},
}
constructor() {
super();
this.bool = true;
this.str = 'not initialized';
this.obj = {data: null};
// not a reactive property
this.foo = 'not initialized';
}
render() {
return html`
<div>Testing...</div>
<div id="bool">${this.bool ? 'A' : 'B'}</div>
<div id="str">${this.str}</div>
<div id="data">data: ${this.obj.data}</div>
`;
}
}

View file

@ -7,6 +7,11 @@ import '../components/my-element.js';
<title>LitElements</title>
</head>
<body>
<my-element foo="bar"></my-element>
<my-element
foo="bar"
str-attr={'initialized'}
bool={false}
obj={{data: 1}}>
</my-element>
</body>
</html>

View file

@ -5,6 +5,7 @@ import { loadFixture } from './test-utils.js';
let fixture;
const NODE_VERSION = parseFloat(process.versions.node);
const stripExpressionMarkers = (html) => html.replace(/<!--\/?lit-part-->/g, '')
before(async () => {
// @lit-labs/ssr/ requires Node 13.9 or higher
@ -27,11 +28,28 @@ describe('LitElement test', () => {
const html = await fixture.readFile('/index.html');
const $ = cheerio.load(html);
// test 1: attributes rendered
// test 1: attributes rendered non reactive properties
expect($('my-element').attr('foo')).to.equal('bar');
// test 2: shadow rendered
expect($('my-element').html()).to.include(`<div>Testing...</div>`);
// test 3: string reactive property set
expect(stripExpressionMarkers($('my-element').html())).to.include(`<div id="str">initialized</div>`);
// test 4: boolean reactive property correctly set
// <my-element bool="false"> Lit will equate to true because it uses
// this.hasAttribute to determine its value
expect(stripExpressionMarkers($('my-element').html())).to.include(`<div id="bool">B</div>`);
// test 5: object reactive property set
// by default objects will be stringifed to [object Object]
expect(stripExpressionMarkers($('my-element').html())).to.include(`<div id="data">data: 1</div>`);
// test 6: reactive properties are not rendered as attributes
expect($('my-element').attr('obj')).to.equal(undefined);
expect($('my-element').attr('bool')).to.equal(undefined);
expect($('my-element').attr('str')).to.equal(undefined);
});
// Skipped because not supported by Lit

View file

@ -28,10 +28,18 @@ function* render(tagName, attrs, children) {
const instance = new LitElementRenderer(tagName);
// LitElementRenderer creates a new element instance, so copy over.
const Ctr = getCustomElementConstructor(tagName);
for (let [name, value] of Object.entries(attrs)) {
instance.setAttribute(name, value);
// check if this is a reactive property
if (name in Ctr.prototype) {
instance.setProperty(name, value);
} else {
instance.setAttribute(name, value);
}
}
instance.connectedCallback();
yield `<${tagName}`;
yield* instance.renderAttributes();
yield `>`;