Skip to content
This repository has been archived by the owner on Dec 5, 2024. It is now read-only.

Commit

Permalink
fix: useMeta refs should be reactive (#81)
Browse files Browse the repository at this point in the history
Co-authored-by: Jacob Andersson <jacob.m.andersson@gmail.com>
  • Loading branch information
danielroe and miii committed May 27, 2020
1 parent e6ffa99 commit 74cb5ef
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 10 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module.exports = {
},
],
'@typescript-eslint/no-inferrable-types': 1,
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/explicit-function-return-type': 0,
},
extends: [
Expand Down
39 changes: 30 additions & 9 deletions src/meta.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import defu from 'defu'
import { getCurrentInstance, toRefs, Ref, reactive } from '@vue/composition-api'
import Vue from 'vue'
import {
getCurrentInstance,
toRefs,
Ref,
reactive,
watch,
} from '@vue/composition-api'

import type { MetaInfo } from 'vue-meta'
import type { UnwrapRef } from '@vue/composition-api/dist/reactivity'
Expand All @@ -18,6 +25,13 @@ type MetaInfoMapper<T> = {
: T[P] | undefined
}

function assign<T extends Record<string, any>>(target: T, source: Partial<T>) {
Object.entries(source).forEach(([key, value]) => {
Vue.set(target, key, value)
})
return target
}

export function createEmptyMeta(): MetaInfoMapper<Required<MetaInfo>> {
return {
__dangerouslyDisableSanitizers: [],
Expand All @@ -42,11 +56,13 @@ export function createEmptyMeta(): MetaInfoMapper<Required<MetaInfo>> {
}
}

export const getHeadOptions = (options: any) => {
const _head: ReactiveHead = reactive<MetaInfo>({})
if (!(options.head instanceof Function)) {
Object.assign(_head, options.head)
}
export const getHeadOptions = (options: {
head: () => Record<string, any> | Record<string, any>
}) => {
const _head: ReactiveHead =
options.head instanceof Function
? reactive<MetaInfo>({})
: reactive<MetaInfo>(options.head)
const head =
options.head instanceof Function
? () => defu(_head, options.head())
Expand Down Expand Up @@ -85,7 +101,12 @@ export const useMeta = <T extends MetaInfo>(init?: T) => {

const { _head } = vm.$options as { _head: ReactiveHead }

Object.assign(_head, createEmptyMeta())
Object.assign(_head, init || {})
return toRefs(_head) as ToRefs<ReturnType<typeof createEmptyMeta> & T>
assign(_head, createEmptyMeta())
assign<MetaInfo>(_head, init || {})

const refs = toRefs(_head) as ToRefs<ReturnType<typeof createEmptyMeta> & T>

if (process.client) watch(Object.values(refs), vm.$meta().refresh)

return refs
}
3 changes: 3 additions & 0 deletions test/e2e/meta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ test('Shows correct title on server-loaded page', async t => {
await navigateTo('/meta')
await t.expect(Selector('title').innerText).eql('newSetTitle')
await expectOnPage('title-newSetTitle')
await t.expect(Selector('title').innerText).eql('mounted title')
await expectOnPage('title-mounted title')
await t.expect(Selector('body').getAttribute('class')).eql('dark-mode mobile')

await t.click(Selector('a').withText('back'))
Expand All @@ -20,4 +22,5 @@ test('Shows correct title on client-loaded page', async t => {

await t.click(Selector('a').withText('meta'))
await t.expect(Selector('title').innerText).eql('newSetTitle')
await t.expect(Selector('title').innerText).eql('mounted title')
})
8 changes: 7 additions & 1 deletion test/fixture/pages/meta.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</template>

<script>
import { defineComponent, useMeta, computed } from 'nuxt-composition-api'
import { defineComponent, useMeta, computed, onMounted } from 'nuxt-composition-api'
export default defineComponent({
head: {},
Expand All @@ -19,6 +19,12 @@ export default defineComponent({
const { title: newImport, bodyAttrs } = useMeta()
newImport.value = 'newSetTitle'
onMounted(() => {
setTimeout(() => {
title.value = 'mounted title'
}, 1000)
})
bodyAttrs.value.class = ['dark-mode', 'mobile']
return { title }
Expand Down

1 comment on commit 74cb5ef

@vercel
Copy link

@vercel vercel bot commented on 74cb5ef May 27, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.