composition-api icon indicating copy to clipboard operation
composition-api copied to clipboard

fix: useFetch in renderless component leads to error "Cannot convert undefined or null to object"

Open thekonz opened this issue 3 years ago • 3 comments

🐛 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:

  1. Download the repo https://github.com/thekonz/reproduce-bug-nuxt-composition-use-fetch
  2. Run yarn dev
  3. See that there is no error, if you set ssr: false in nuxt.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.

thekonz avatar Jan 25 '22 13:01 thekonz

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.

thekonz avatar Jan 25 '22 15:01 thekonz

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 avatar Feb 07 '22 18:02 Chapaev17

@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 }
}

maninak avatar Feb 07 '22 18:02 maninak