fix: useFetch in renderless component leads to error "Cannot convert undefined or null to object"
🐛 The bug
I have a renderless component that uses useFetch. In ssr: true mode, it crashes the app with this error:
Cannot convert undefined or null to object in serverPrefetch
node_modules/@nuxtjs/composition-api/dist/runtime/index.mjs
: vm._fetchKey || vm.$ssrContext.fetchCounters['']++
if (!vm.$vnode.data) vm.$vnode.data = {}
const attrs = (vm.$vnode.data.attrs = vm.$vnode.data.attrs || {})
attrs['data-fetch-key'] = vm._fetchKey
const data = { ...vm._data }
Object.entries(vm.__composition_api_state__.rawBindings).forEach(
([key, val]) => {
if (val instanceof Function || val instanceof Promise) return
data[key] = isRef(val) ? val.value : val
}
)
The issue is that vm.__composition_api_state__.rawBindings is not set for a renderless component.
🛠️ To reproduce Steps to reproduce the behavior:
- Download the repo https://github.com/thekonz/reproduce-bug-nuxt-composition-use-fetch
- Run
yarn dev - See that there is no error, if you set
ssr: falseinnuxt.config.js
Repo for reproduction: https://github.com/thekonz/reproduce-bug-nuxt-composition-use-fetch Component: https://github.com/thekonz/reproduce-bug-nuxt-composition-use-fetch/blob/master/components/outer.vue
🌈 Expected behaviour
I expect it to work the same on ssr as in client.
I wrote the same with bridge in this branch https://github.com/thekonz/reproduce-bug-nuxt-composition-use-fetch/tree/bridge It works, but using bridge would be quite a bit of work in our project, so I hope we can get a fix or a recommendation here.
Another workaround is to make the component render a div with a slot and pass props to the slot without using () => slots.default(), but then the component returns one root node instead of many.
Same error Cannot convert undefined or null to object when using useFetch, when setup function returns tsx. When using the render function, everything works fine.
@Chapaev17 that's weird that you only get this with JSX, because I came to find this ticket after getting this error, even though I'm using render functions a.k.a. h().
For reference here's my code
// useCmsifiedPage.ts
import type { Ref } from '@nuxtjs/composition-api'
import { usePageMeta } from '~/composables'
import type { Page } from '~/types'
import { getSections } from '~/utils'
type MetaToAppend = Parameters<typeof usePageMeta>['1']
interface Props {
slug?: string
metaToAppend?: MetaToAppend
}
export function useCmsifiedPage(strapiResponse: Ref<Page[] | null>, props: Props = {}) {
const page = computed(() => strapiResponse.value?.[0])
const sections = computed(() => getSections(page?.value))
function renderPage() {
return h('div', { class: 'mt-6' }, [
Object.entries(sections.value).map(([componentName, componentProps], index) =>
h(`lazy-${componentName}`, {
props: componentProps,
key: `${componentName}-${index}`,
class: 'mb-6',
}),
),
])
}
usePageMeta(page, props.metaToAppend)
return { page, sections, renderPage }
}