Skip to content

Commit

Permalink
fix: preserve reactive objects on useFetch hydration (#541)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielroe authored Sep 1, 2021
1 parent 534a38b commit 4c3e734
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 26 deletions.
59 changes: 38 additions & 21 deletions src/runtime/composables/fetch.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
isRef,
isReactive,
onBeforeMount,
onServerPrefetch,
reactive,
Expand Down Expand Up @@ -129,6 +130,41 @@ const setFetchState = (vm: AugmentedComponentInstance) => {
})
}

const mergeDataOnMount = (data: Record<string, any>) => {
const vm = getCurrentInstance() as AugmentedComponentInstance | undefined
if (!vm) throw new Error('This must be called within a setup function.')

onBeforeMount(() => {
// Merge data
for (const key in data) {
try {
// Assign missing properties
if (key in vm) {
const _key = key as keyof typeof vm
// Skip functions (not stringifiable)
if (typeof vm[_key] === 'function') continue
// Preserve reactive objects
if (isReactive(vm[_key])) {
// Unset keys that do not exist in incoming data
for (const k in vm[_key]) {
if (!(k in data[key])) {
delete vm[_key][k]
}
}
Object.assign(vm[_key], data[key])
continue
}
}
set(vm, key, data[key])
} catch (e) {
if (process.env.NODE_ENV === 'development')
// eslint-disable-next-line
console.warn(`Could not hydrate ${key}.`)
}
}
})
}

const loadFullStatic = (vm: AugmentedComponentInstance) => {
vm._fetchKey = getKey(vm)
// Check if component has been fetched on server
Expand All @@ -151,12 +187,7 @@ const loadFullStatic = (vm: AugmentedComponentInstance) => {
return
}

onBeforeMount(() => {
// Merge data
for (const key in data) {
set(vm, key, data[key])
}
})
mergeDataOnMount(data)
}

async function serverPrefetch(vm: AugmentedComponentInstance) {
Expand Down Expand Up @@ -319,21 +350,7 @@ export const useFetch = (callback: Fetch) => {
return result()
}

onBeforeMount(() => {
// Merge data
for (const key in data) {
try {
if (key in vm && typeof vm[key as keyof typeof vm] === 'function') {
continue
}
set(vm, key, data[key])
} catch (e) {
if (process.env.NODE_ENV === 'development')
// eslint-disable-next-line
console.warn(`Could not hydrate ${key}.`)
}
}
})
mergeDataOnMount(data)

return result()
}
12 changes: 7 additions & 5 deletions test/fixture/pages/ttfb.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
<template>
<main>TTFB: {{ ttfb }}ms</main>
<main>TTFB: {{ dataset.ttfb }}ms</main>
</template>

<script>
import {
defineComponent,
ref,
reactive,
useFetch,
onMounted,
} from '@nuxtjs/composition-api'
export default defineComponent({
setup() {
const dataset = reactive({
ttfb: -1
})
useFetch(() => {})
const ttfb = ref(-1)
onMounted(() => {
ttfb.value =
dataset.ttfb =
globalThis.performance.getEntriesByType('navigation')[0].responseStart
})
return {
ttfb,
dataset,
}
},
})
Expand Down

0 comments on commit 4c3e734

Please sign in to comment.