Skip to content

Commit

Permalink
@query and @QueryAll return null or [] before first update (#2065)
Browse files Browse the repository at this point in the history
Fixes #2062. To match Lit1 behavior, the `@query` decorator returns `null` (rather than `undefined`) if a decorated property is accessed before first update. When the `cache` setting is true, the first result is always cached and it is either `null` or the queried element. Likewise, a `@queryAll` decorated property returns `[]` rather than `undefined`.
  • Loading branch information
Steve Orvell committed Aug 20, 2021
1 parent b69abca commit 8b6e241
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/twelve-moons-reply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@lit/reactive-element': patch
---

Fixes #2062. To match Lit1 behavior, the @query decorator returns null (rather than undefined) if a decorated property is accessed before first update. Likewise, a @queryAll decorated property returns [] rather than undefined.
2 changes: 1 addition & 1 deletion packages/reactive-element/src/decorators/query-all.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function queryAll(selector: string) {
return decorateProperty({
descriptor: (_name: PropertyKey) => ({
get(this: ReactiveElement) {
return this.renderRoot?.querySelectorAll(selector);
return this.renderRoot?.querySelectorAll(selector) ?? [];
},
enumerable: true,
configurable: true,
Expand Down
4 changes: 2 additions & 2 deletions packages/reactive-element/src/decorators/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ export function query(selector: string, cache?: boolean) {
descriptor: (name: PropertyKey) => {
const descriptor = {
get(this: ReactiveElement) {
return this.renderRoot?.querySelector(selector);
return this.renderRoot?.querySelector(selector) ?? null;
},
enumerable: true,
configurable: true,
Expand All @@ -59,7 +59,7 @@ export function query(selector: string, cache?: boolean) {
) {
(this as unknown as {[key: string]: Element | null})[
key as string
] = this.renderRoot?.querySelector(selector);
] = this.renderRoot?.querySelector(selector) ?? null;
}
return (this as unknown as {[key: string]: Element | null})[
key as string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,10 @@ import {assert} from '@esm-bundle/chai';
Array.from(el.renderRoot.querySelectorAll('span'))
);
});

test('returns empty array when no match and accessed before first update', () => {
const notYetUpdatedEl = new C();
assert.lengthOf(notYetUpdatedEl.spans, 0);
assert.deepEqual(Array.from(notYetUpdatedEl.spans), []);
});
});
13 changes: 13 additions & 0 deletions packages/reactive-element/src/test/decorators/query_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ import {assert} from '@esm-bundle/chai';
assert.isNull(el.span);
});

test('returns null when no match and accessed before first update', () => {
const notYetUpdatedEl = new C();
assert.isNull(notYetUpdatedEl.span);
});

test('returns cached value', async () => {
el.condition = true;
await el.updateComplete;
Expand All @@ -84,4 +89,12 @@ import {assert} from '@esm-bundle/chai';
assert.instanceOf(el.span, HTMLSpanElement);
assert.notEqual(el.span, el.renderRoot.querySelector('span'));
});

test('returns cached value when accessed before first update', async () => {
const notYetUpdatedEl = new C();
assert.equal(notYetUpdatedEl.divCached, null);
container.appendChild(notYetUpdatedEl);
await notYetUpdatedEl.updateComplete;
assert.equal(notYetUpdatedEl.divCached, null);
});
});

0 comments on commit 8b6e241

Please sign in to comment.