Simon
Simon
NNuxt
Created by Simon on 2/6/2025 in #❓・help
Resolving components in JSX
Here's a funny one. I would like to write some JSX for dynamically mounting a component, and then I would like to compile the result into a statically servable set of files. Seems straightforward enough, and indeed the following works like a charm.
<script setup lang="jsx">
const Jsx = ref(<p>Some text</p>);
function loadSomeComponent() {
Jsx.value = <p><SomeComponent /></p>;
}
</script>

<template>
<Jsx />
<button @click="loadSomeComponent()">Load component directly</button>
</template>
<script setup lang="jsx">
const Jsx = ref(<p>Some text</p>);
function loadSomeComponent() {
Jsx.value = <p><SomeComponent /></p>;
}
</script>

<template>
<Jsx />
<button @click="loadSomeComponent()">Load component directly</button>
</template>
For some weird reason, though, the above break down once the button is moved into the <slot> of another component.
<script setup lang="jsx">
const Jsx = ref(<p>Some text</p>);
function loadSomeComponent() {
Jsx.value = <p><SomeComponent /></p>;
}
</script>

<template>
<Jsx />
<PassThrough>
<button @click="loadSomeComponent()">Load component from slot</button>
</PassThrough>
</template>

<!-- components/PassThrough.vue -->
<template>
<slot />
</template>
<script setup lang="jsx">
const Jsx = ref(<p>Some text</p>);
function loadSomeComponent() {
Jsx.value = <p><SomeComponent /></p>;
}
</script>

<template>
<Jsx />
<PassThrough>
<button @click="loadSomeComponent()">Load component from slot</button>
</PassThrough>
</template>

<!-- components/PassThrough.vue -->
<template>
<slot />
</template>
In this second example, clicking the button just replaces <Jsx /> with <somecomponent />, which of course isn't very helpful because the browser doesn't know what to do with this tag. I can fix the second scenario by importing SomeComponent explicitly,
import SomeComponent from '~/components/SomeComponent.vue';
import SomeComponent from '~/components/SomeComponent.vue';
but having to explicitly import all components used in my JSX code is tedious. Moreover, forgetting to import some component results in a silent error, which is a maintainability nightmare. Does anyone have an idea what could be the issue here, and whether the second scenario can be saved in any way that is less brittle than "import all components"? I have attached an MWE to reproduce the problem. Please remember that I need to served this site statically, i.e. the site should be served using npm run build && npx serve .output/public. Both of the above scenarios work fine with npm run dev, so you won't be able to reproduce my findings with that.
6 replies