Skip to content

Commit

Permalink
fix: serialize var prop
Browse files Browse the repository at this point in the history
  • Loading branch information
Varixo committed Dec 25, 2024
1 parent d266bdd commit 6578707
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 11 deletions.
5 changes: 5 additions & 0 deletions .changeset/witty-balloons-thank.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@qwik.dev/core': patch
---

fix: serialize var prop
21 changes: 10 additions & 11 deletions packages/qwik/src/core/client/vnode-diff.ts
Original file line number Diff line number Diff line change
Expand Up @@ -723,8 +723,7 @@ export const vnode_diff = (
const jsxAttrs = [] as ClientAttrs;
const props = jsx.varProps;
for (const key in props) {
let value = props[key];
value = serializeAttribute(key, value, scopedStyleIdPrefix);
const value = props[key];
if (value != null) {
mapArray_set(jsxAttrs, key, value, 0);
}
Expand Down Expand Up @@ -791,7 +790,7 @@ export const vnode_diff = (
value = untrack(() => value.value);
}

vnode_setAttr(journal, vnode, key, value);
vnode_setAttr(journal, vnode, key, serializeAttribute(key, value, scopedStyleIdPrefix));
if (value === null) {
// if we set `null` than attribute was removed and we need to shorten the dstLength
dstLength = dstAttrs.length;
Expand Down Expand Up @@ -830,20 +829,20 @@ export const vnode_diff = (
if (dstKey && isHtmlAttributeAnEventName(dstKey)) {
patchEventDispatch = true;
dstIdx++;
} else {
record(dstKey!, null);
} else if (dstKey) {
record(dstKey, null);
dstIdx--;
}
dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
} else if (dstKey == null) {
// Destination has more keys, so we need to insert them from source.
const isEvent = isJsxPropertyAnEventName(srcKey);
if (isEvent) {
if (srcKey && isEvent) {
// Special handling for events
patchEventDispatch = true;
recordJsxEvent(srcKey, srcAttrs[srcIdx]);
} else {
record(srcKey!, srcAttrs[srcIdx]);
} else if (srcKey) {
record(srcKey, srcAttrs[srcIdx]);
}
srcIdx++;
srcKey = srcIdx < srcLength ? srcAttrs[srcIdx++] : null;
Expand Down Expand Up @@ -874,11 +873,11 @@ export const vnode_diff = (
dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
} else {
// Source is missing the key, so we need to remove it from destination.
if (isHtmlAttributeAnEventName(dstKey)) {
if (dstKey && isHtmlAttributeAnEventName(dstKey)) {
patchEventDispatch = true;
dstIdx++;
} else {
record(dstKey!, null);
} else if (dstKey) {
record(dstKey, null);
dstIdx--;
}
dstKey = dstIdx < dstLength ? dstAttrs[dstIdx++] : null;
Expand Down
73 changes: 73 additions & 0 deletions packages/qwik/src/core/tests/render-styles.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import {
Fragment as Component,
component$,
createContextId,
Fragment,
Fragment as Signal,
type Signal as SignalType,
useStore,
useContext,
useComputed$,
useSignal,
useContextProvider,
} from '@qwik.dev/core';
import { domRender, ssrRenderToDom, trigger } from '@qwik.dev/core/testing';
import { describe, expect, it } from 'vitest';
Expand Down Expand Up @@ -70,4 +76,71 @@ describe.each([
</Component>
);
});

it('should render styles from computed and context', async () => {
const Ctx = createContextId<{
val: SignalType<Record<string, number>>;
abc: SignalType<number>;
}>('test');

const Child = component$(() => {
const ctx = useContext(Ctx);
// use computed to add context value as dependency
const color = useComputed$(() => (ctx.abc.value > 0 ? 'red' : 'green'));
return (
// use spread props to convert div props to var props
<div style={{ color: color.value }} {...ctx.val.value}>
Abcd
</div>
);
});

const Parent = component$(() => {
const signal = useSignal(0);
// use computed to create a new object
const comp = useComputed$<Record<string, number>>(() => ({
'data-value': signal.value,
}));
useContextProvider(Ctx, {
val: comp,
abc: signal,
});
return (
<div>
<Child />
<button onClick$={() => signal.value++}></button>
</div>
);
});

const { vNode, container } = await render(<Parent />, { debug });

expect(vNode).toMatchVDOM(
<Component ssr-required>
<div>
<Component ssr-required>
<div style="color:green" data-value={0}>
Abcd
</div>
</Component>
<button />
</div>
</Component>
);

await trigger(container.element, 'button', 'click');

expect(vNode).toMatchVDOM(
<Component ssr-required>
<div>
<Component ssr-required>
<div style="color:red" data-value={1}>
Abcd
</div>
</Component>
<button />
</div>
</Component>
);
});
});

0 comments on commit 6578707

Please sign in to comment.