Skip to content

Commit

Permalink
fix: destructured props for inline components
Browse files Browse the repository at this point in the history
  • Loading branch information
Varixo committed Dec 25, 2024
1 parent 7160354 commit 48af55c
Show file tree
Hide file tree
Showing 9 changed files with 381 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .changeset/thirty-ravens-draw.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@qwik.dev/core': patch
---

fix: destructured props for inline components
64 changes: 64 additions & 0 deletions packages/qwik/src/core/tests/use-store.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,70 @@ describe.each([
</Component>
);
});

it('should rerender inner inline component with destructured props', async () => {
interface InnerButtonProps {
text: string;
isActive: boolean;
onClick$: PropsOf<'button'>['onClick$'];
}

const Parent = component$(() => {
const store = useStore({
selectedOutputDetail: 'console',
});

const InnerButton = (props: InnerButtonProps) => {
return (
<button
key={props.text}
class={{ 'active-tab': props.isActive, 'repl-tab-button': true }}
onClick$={props.onClick$}
>
{props.text}
</button>
);
};

const InnerButtonWrapper = ({ data }: { data: any }) => {
return (
<InnerButton
text="Options"
isActive={data.selectedOutputDetail === 'options'}
onClick$={() => {
data.selectedOutputDetail = 'options';
}}
/>
);
};

return <InnerButtonWrapper data={store} />;
});

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

expect(vNode).toMatchVDOM(
<Component ssr-required>
<InlineComponent>
<InlineComponent>
<button class="repl-tab-button">Options</button>
</InlineComponent>
</InlineComponent>
</Component>
);

await trigger(document.body, 'button', 'click');

expect(vNode).toMatchVDOM(
<Component ssr-required>
<InlineComponent>
<InlineComponent>
<button class="active-tab repl-tab-button">Options</button>
</InlineComponent>
</InlineComponent>
</Component>
);
});
});

describe('SerializationConstant at the start', () => {
Expand Down
21 changes: 21 additions & 0 deletions packages/qwik/src/optimizer/core/src/props_destructuring.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,27 @@ impl<'a> PropsDestructuring<'a> {
}

impl<'a> VisitMut for PropsDestructuring<'a> {
fn visit_mut_arrow_expr(&mut self, node: &mut ast::ArrowExpr) {
if node.params.len() == 1 {
// probably an inline component
if matches!(
&node.body,
box ast::BlockStmtOrExpr::Expr(box ast::Expr::Call(_))
) {
// function without return statement
self.transform_component_props(node);
} else if matches!(
&node.body,
box ast::BlockStmtOrExpr::BlockStmt(ast::BlockStmt { stmts, .. })
if stmts.iter().any(|stmt| matches!(stmt, ast::Stmt::Return(_)))
) {
// function with return statement
self.transform_component_props(node);
}
}
node.visit_mut_children_with(self);
}

fn visit_mut_call_expr(&mut self, node: &mut ast::CallExpr) {
if let ast::Callee::Expr(box ast::Expr::Ident(ref ident)) = &node.callee {
if id_eq!(ident, &self.component_ident) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
source: packages/qwik/src/optimizer/core/src/test.rs
assertion_line: 3651
expression: output
snapshot_kind: text
---
==INPUT==


export default ({ data }: { data: any }) => {
return (
<div
data-is-active={data.selectedOutputDetail === 'options'}
onClick$={() => {
data.selectedOutputDetail = 'options';
}}
/>
);
};

============================= test.js ==

import { _fnSignal } from "@qwik.dev/core";
import { qrl } from "@qwik.dev/core";
import { _jsxSorted } from "@qwik.dev/core";
export default ((props)=>{
return /*#__PURE__*/ _jsxSorted("div", null, {
"data-is-active": _fnSignal((p0)=>p0.data.selectedOutputDetail === 'options', [
props
], 'p0.data.selectedOutputDetail==="options"'),
onClick$: /*#__PURE__*/ qrl(()=>import("./test.tsx_test_div_onClick_GbMO6TGQv9M"), "test_div_onClick_GbMO6TGQv9M", [
props
])
}, null, 3, "u6_0");
});


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;AACE,eAAe,CAAA;IACP,qBACE,WAAC;QACC,gBAAc,kBAAE,GAHV,KAGe,oBAAoB,KAAK;;;QAC9C,QAAQ;;;;AAKpB,CAAA,EAAE\"}")
============================= test.tsx_test_div_onClick_GbMO6TGQv9M.js (ENTRY POINT)==

import { useLexicalScope } from "@qwik.dev/core";
export const test_div_onClick_GbMO6TGQv9M = ()=>{
const [props] = useLexicalScope();
props.data.selectedOutputDetail = 'options';
};


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";4CAKwB;;IACR,MALI,KAKC,oBAAoB,GAAG\"}")
/*
{
"origin": "test.tsx",
"name": "test_div_onClick_GbMO6TGQv9M",
"entry": null,
"displayName": "test.tsx_test_div_onClick",
"hash": "GbMO6TGQv9M",
"canonicalFilename": "test.tsx_test_div_onClick_GbMO6TGQv9M",
"path": "",
"extension": "js",
"parent": null,
"ctxKind": "eventHandler",
"ctxName": "onClick$",
"captures": true,
"loc": [
181,
259
]
}
*/
== DIAGNOSTICS ==

[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
source: packages/qwik/src/optimizer/core/src/test.rs
assertion_line: 3673
expression: output
snapshot_kind: text
---
==INPUT==


export default (props: { data: any }) => {
const { data } = props;
return (
<div
data-is-active={data.selectedOutputDetail === 'options'}
onClick$={() => {
data.selectedOutputDetail = 'options';
}}
/>
);
};

============================= test.js ==

import { _fnSignal } from "@qwik.dev/core";
import { qrl } from "@qwik.dev/core";
import { _jsxSorted } from "@qwik.dev/core";
export default ((props)=>{
return /*#__PURE__*/ _jsxSorted("div", null, {
"data-is-active": _fnSignal((p0)=>p0.data.selectedOutputDetail === 'options', [
props
], 'p0.data.selectedOutputDetail==="options"'),
onClick$: /*#__PURE__*/ qrl(()=>import("./test.tsx_test_div_onClick_GbMO6TGQv9M"), "test_div_onClick_GbMO6TGQv9M", [
props
])
}, null, 3, "u6_0");
});


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;AACE,eAAe,CAAA,CAAC;IAER,qBACE,WAAC;QACC,gBAAc,kBAAE,GAHlB,KAGuB,oBAAoB,KAAK;;;QAC9C,QAAQ;;;;AAKpB,CAAA,EAAE\"}")
============================= test.tsx_test_div_onClick_GbMO6TGQv9M.js (ENTRY POINT)==

import { useLexicalScope } from "@qwik.dev/core";
export const test_div_onClick_GbMO6TGQv9M = ()=>{
const [props] = useLexicalScope();
props.data.selectedOutputDetail = 'options';
};


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";4CAMwB;;IAJH,MAAT,KAKS,oBAAoB,GAAG\"}")
/*
{
"origin": "test.tsx",
"name": "test_div_onClick_GbMO6TGQv9M",
"entry": null,
"displayName": "test.tsx_test_div_onClick",
"hash": "GbMO6TGQv9M",
"canonicalFilename": "test.tsx_test_div_onClick_GbMO6TGQv9M",
"path": "",
"extension": "js",
"parent": null,
"ctxKind": "eventHandler",
"ctxName": "onClick$",
"captures": true,
"loc": [
206,
284
]
}
*/
== DIAGNOSTICS ==

[]
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
---
source: packages/qwik/src/optimizer/core/src/test.rs
assertion_line: 3673
expression: output
snapshot_kind: text
---
==INPUT==


export default ({ data }: { data: any }) =>
<div
data-is-active={data.selectedOutputDetail === 'options'}
onClick$={() => {
data.selectedOutputDetail = 'options';
}}
/>;

============================= test.js ==

import { _fnSignal } from "@qwik.dev/core";
import { qrl } from "@qwik.dev/core";
import { _jsxSorted } from "@qwik.dev/core";
export default ((props)=>/*#__PURE__*/ _jsxSorted("div", null, {
"data-is-active": _fnSignal((p0)=>p0.data.selectedOutputDetail === 'options', [
props
], 'p0.data.selectedOutputDetail==="options"'),
onClick$: /*#__PURE__*/ qrl(()=>import("./test.tsx_test_div_onClick_GbMO6TGQv9M"), "test_div_onClick_GbMO6TGQv9M", [
props
])
}, null, 3, "u6_0"));


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";;;AACE,eAAe,CAAA,uBACL,WAAC;QACC,gBAAc,kBAAE,GAFV,KAEe,oBAAoB,KAAK;;;QAC9C,QAAQ;;;uBAGT,EAAE\"}")
============================= test.tsx_test_div_onClick_GbMO6TGQv9M.js (ENTRY POINT)==

import { useLexicalScope } from "@qwik.dev/core";
export const test_div_onClick_GbMO6TGQv9M = ()=>{
const [props] = useLexicalScope();
props.data.selectedOutputDetail = 'options';
};


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";4CAIwB;;IACR,MAJI,KAIC,oBAAoB,GAAG\"}")
/*
{
"origin": "test.tsx",
"name": "test_div_onClick_GbMO6TGQv9M",
"entry": null,
"displayName": "test.tsx_test_div_onClick",
"hash": "GbMO6TGQv9M",
"canonicalFilename": "test.tsx_test_div_onClick_GbMO6TGQv9M",
"path": "",
"extension": "js",
"parent": null,
"ctxKind": "eventHandler",
"ctxName": "onClick$",
"captures": true,
"loc": [
161,
239
]
}
*/
== DIAGNOSTICS ==

[]
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,13 @@ Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"ma
import { Header } from "./test";
export const Header_component_1_2B8d0oH9ZWc = (hola)=>{
const hola = this;
const { something, styff } = hola;
hola.nothere.stuff[global];
return <Header/>;
};
export { _hW } from "@qwik.dev/core";


Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";8CAIU,CAAC;IACT,MAAM,OAAO,IAAI;IACjB,MAAM,EAAC,SAAS,EAAE,KAAK,EAAC,GAAG;IACb,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO;IACxC,QACE;AAEH\"}")
Some("{\"version\":3,\"sources\":[\"/user/qwik/src/test.tsx\"],\"names\":[],\"mappings\":\";8CAIU,CAAC;IACT,MAAM,OAAO,IAAI;IAEH,KAAK,OAAO,CAAC,KAAK,CAAC,OAAO;IACxC,QACE;AAEH\"}")
/*
{
"origin": "test.tsx",
Expand Down
Loading

0 comments on commit 48af55c

Please sign in to comment.