vuejs / composition-api

Composition API plugin for Vue 2
https://composition-api.vuejs.org/
MIT License
4.19k stars 342 forks source link

Cannot read property '$createElement' of undefined #168

Closed dugajean closed 5 years ago

dugajean commented 5 years ago

I'm using Nuxt, Nuxt Typescript, TSX and Vue Composition API. When I converted a .vue component into a .tsx one, without a render method, but instead returning the JSX from the setup function, I get the following error during runtime:

Cannot read property '$createElement' of undefined

From my stack listed above, I didn't know which part could be causing this problem, so I'm presuming it has something to do with the Composition API package. I'm also quite unfamiliar with the Composition API and I'm trying to learn - could be I'm just doing something wrong here?

My component looks like this:

import { createComponent, reactive } from '@vue/composition-api'
import InputField from '@/components/InputField.vue'
import PageSection from '@/components/PageSection.vue'
import countryData from '@/data/countries.json'

export default createComponent({
  components: {
    InputField,
    PageSection
  },

  setup() {
    const state = reactive({
      destination: null,
      whenDate: {
        start: null,
        span: null
      },
      travelType: null,
      countries: { ...countryData }
    })

    return () => (
      <PageSection classes="md:pt-40 pt-8 bg-gray-100" heading="Where do you wanna go today?">
        <svg slot="top" class="absolute top-0 left-0" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1440 320">
          <path
            fill="#ebeff2"
            fill-opacity="1"
            d="M0,96L80,101.3C160,107,320,117,480,112C640,107,800,85,960,90.7C1120,96,1280,128,1360,144L1440,160L1440,0L1360,0C1280,0,1120,0,960,0C800,0,640,0,480,0C320,0,160,0,80,0L0,0Z"
          ></path>
        </svg>

        <form class="flex justify-center mt-4 md:mt-12 -mx-1 text-center flex-wrap">
          <InputField
            v-model={state.destination}
            type="select"
            placeholder="Where are you going?"
            width="3/12"
            options={state.countries}
            required={true}
          />
          <InputField
            v-model={state.whenDate}
            type="date"
            placeholder="When are you travelling?"
            width="3/12"
            required={true}
          />
          <InputField
            v-model={state.travelType}
            placeholder="Tell us what you're doing there"
            width="3/12"
            required={true}
          />
          <div class="px-1 w-full md:w-2/12 mt-3 md:mt-0">
            <button class="btn btn-primary bg-primary w-full h-full">Search</button>
          </div>
        </form>
      </PageSection>
    )
  }
})

Environment Info:

  System:
    OS: Windows 10
    CPU: (8) x64 Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  Binaries:
    Node: 12.13.0 - C:\Program Files\nodejs\node.EXE     
    Yarn: 1.19.1 - ~\AppData\Local\Yarn\bin\yarn.CMD     
    npm: 6.12.0 - C:\Program Files\nodejs\npm.CMD        
  Browsers:
    Edge: 44.19008.1.0
  npmPackages:
    @fortawesome/vue-fontawesome:  0.1.7 
    @nuxt/vue-app:  2.10.1 
    @nuxt/vue-renderer:  2.10.1 
    @vue/babel-helper-vue-jsx-merge-props:  1.0.0        
    @vue/babel-plugin-transform-vue-jsx:  1.0.0 
    @vue/babel-preset-jsx:  1.1.1 
    @vue/babel-sugar-functional-vue:  1.0.0 
    @vue/babel-sugar-inject-h:  1.0.0 
    @vue/babel-sugar-v-model:  1.1.1
    @vue/babel-sugar-v-on:  1.1.0
    @vue/component-compiler-utils:  3.0.0
    @vue/composition-api: ^0.3.2 => 0.3.2
    @vue/eslint-config-prettier: ^5.0.0 => 5.0.0
    eslint-plugin-vue: ^5.2.2 => 5.2.3
    typescript:  3.6.4
    vue:  2.6.10
    vue-carousel: ^0.18.0 => 0.18.0
    vue-cli-webpack:  1.0.0
    vue-client-only:  2.0.0
    vue-eslint-parser:  5.0.0 (2.0.3)
    vue-hot-reload-api:  2.3.4
    vue-loader:  15.7.1
    vue-meta:  2.3.1
    vue-no-ssr:  1.1.1
    vue-router:  3.0.7
    vue-server-renderer:  2.6.10
    vue-spinner: ^1.0.3 => 1.0.3
    vue-style-loader:  4.1.2
    vue-template-compiler:  2.6.10
    vue-template-es2015-compiler:  1.9.1
    vuex:  3.1.1
  npmGlobalPackages:
    @vue/cli: Not Found
leopiccionia commented 5 years ago

The plugin currently doesn't allow setup returning a render function, as stated in README.

beeplin commented 5 years ago

In fact it works in this way:

  1. Make h globally available: import createElement as h from '@vue/composition-api'

  2. Make sure both setup and the returned function are arrow functions: setup: () => { return () => <div /> }

dugajean commented 5 years ago

@leopiccionia how do I access props and reactive data from the render function then?

@beeplin This didn't work for me

beeplin commented 5 years ago

@dugajean Try this: https://codesandbox.io/s/vue-render-function-sjnir

image

dugajean commented 5 years ago

@beeplin That worked! Looks hacky though, dang.

liximomo commented 5 years ago

@dugajean https://github.com/liximomo/vue-composition-api-tsx-example

dvic commented 5 years ago

@dugajean the important thing here is to use the babel preset vca-jsx (as you can see in the example given).

gd4Ark commented 4 years ago

This is working in my nuxt project:https://qiita.com/nkjmsss/items/7c61193efe390c14aa16#%E3%82%B5%E3%83%B3%E3%83%97%E3%83%AB

lulei90 commented 2 years ago

in version '1.6.2' The requested module '/node_modules/.vite/@vue_composition-api.js?v=82ecb7cd' does not provide an export named 'createComponent'

mateusfmello commented 1 year ago

In Vue 2, import from vue

import {h} from "vue"