8

I'm trying to render a template in Vue 3. The template contains a component, which is locally registered on the instance.

import template from './template'
import RenderlessPagination from "./RenderlessPagination";
import {h, resolveComponent} from 'vue'

export default {
    name: 'Pagination',
    components: {RenderlessPagination},
    provide() {
        return {
            Page: () => this.value,
            perPage: () => this.perPage,
            records: () => this.records
        }
    },
    render() {
        const RLPagination = resolveComponent('renderless-pagination');

        return h(RLPagination, {
            slots: {
                default: function (props) {
                    return props.override ? h(
                        props.override,
                        {
                            attrs: {props}
                        }
                    ) : template(props)(h)
                }
            }
        })
    },
    props: {
        value: {
            type: Number,
            required: true,
            validator(val) {
                return val > 0;
            }
        },
        records: {
            type: Number,
            required: true
        },
        perPage: {
            type: Number,
            default: 25
        },
        options: {
            type: Object
        }
    },
    data: function () {
        return {
            aProps: {
                role: "button"
            }
        }
    }
}

This results in a following run-time warning:

resolveComponent can only be used in render() or setup()

In addition the renderless-pagination component is not compiled, but just added as-is to the HTML:

<renderless-pagination slots=[Object Object]></renderless-pagination>

As you can see I am using resolveComponent in the render function, which makes me wonder why it complains, and why the renderless-pagination component is not compiled.

I checked the value returned from the resolveComponent call, and it just returns the component's name, i.e renderless-pagination.

What am I missing here?

EDIT:

Following @skirtle's comment I have removed the duplicate Vue instance from the package, using the externals option in webpack. However, I am still receiving the same error:

resolveComponent can only be used in render() or setup()

Relavant webpack config:

  output: {
        path: path.resolve(__dirname, './dist'),
        publicPath: '/dist/',
        filename: 'vue-pagination-2.min.js',
        library:'Pagination',
        libraryTarget: "commonjs"
    },
    externals: {
        vue: {
            root: 'Vue',
            commonjs: 'vue',
            commonjs2: 'vue',
            amd: 'vue'
        }
    }
Matanya
  • 6,233
  • 9
  • 47
  • 80
  • 3
    Is it possible that you're pulling in two copies of Vue? Not necessarily different versions, just two copies of the same version being pulled in by different parts of your build? The full stack trace may help to identify this, as `resolveComponent` may be calling out to a different Vue from the rest of the rendering process. – skirtle Oct 06 '20 at 18:57
  • @skirtle Yes! I believe that is the reason. I am upgrading a package so there is a different vue instance rendered on the package's codebase. Thanks :) – Matanya Oct 06 '20 at 19:16

2 Answers2

2

vue.config.js

add

module.exports = {
    ...
    configureWebpack:{
        resolve:{
            alias:{
               vue: path.resolve('./node_modules/vue')
            }
        }
    }
}
shunyue
  • 21
  • 2
0

Thanks to @skirtle's comment I have removed the duplicate Vue instance but was still getting the same error.

What ended up working is passing the component instance itself to the h function, like so:

render() {
        return h(RenderlessPagination, {}, {
                default: function (props) {
                    return props.override ? h(
                        props.override,
                        {
                            props
                        }
                    ) : template(props)(h)
                }
        })

I suppose that's what resolveComponent does behind the scenes... Oh,well

Matanya
  • 6,233
  • 9
  • 47
  • 80