mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 00:52:01 +00:00
feat(nuxt): emit error if <NuxtIsland>
can't fetch island (#25798)
This commit is contained in:
parent
83314f1c95
commit
f0442d0ddb
@ -60,3 +60,11 @@ Some slots are reserved to `NuxtIsland` for special cases.
|
|||||||
- `refresh()`
|
- `refresh()`
|
||||||
- **type**: `() => Promise<void>`
|
- **type**: `() => Promise<void>`
|
||||||
- **description**: force refetch the server component by refetching it.
|
- **description**: force refetch the server component by refetching it.
|
||||||
|
|
||||||
|
## Events
|
||||||
|
|
||||||
|
- `error`
|
||||||
|
- **parameters**:
|
||||||
|
- **error**:
|
||||||
|
- **type**: `unknown`
|
||||||
|
- **description**: emitted when when `NuxtIsland` fails to fetch the new island.
|
||||||
|
@ -69,7 +69,8 @@ export default defineComponent({
|
|||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async setup (props, { slots, expose }) {
|
emits: ['error'],
|
||||||
|
async setup (props, { slots, expose, emit }) {
|
||||||
let canTeleport = import.meta.server
|
let canTeleport = import.meta.server
|
||||||
const teleportKey = ref(0)
|
const teleportKey = ref(0)
|
||||||
const key = ref(0)
|
const key = ref(0)
|
||||||
@ -208,11 +209,12 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
error.value = e
|
error.value = e
|
||||||
|
emit('error', e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
expose({
|
expose({
|
||||||
refresh: () => fetchComponent(true)
|
refresh: () => fetchComponent(true),
|
||||||
})
|
})
|
||||||
|
|
||||||
if (import.meta.hot) {
|
if (import.meta.hot) {
|
||||||
|
@ -9,7 +9,8 @@ export const createServerComponent = (name: string) => {
|
|||||||
name,
|
name,
|
||||||
inheritAttrs: false,
|
inheritAttrs: false,
|
||||||
props: { lazy: Boolean },
|
props: { lazy: Boolean },
|
||||||
setup (props, { attrs, slots, expose }) {
|
emits: ['error'],
|
||||||
|
setup (props, { attrs, slots, expose, emit }) {
|
||||||
const islandRef = ref<null | typeof NuxtIsland>(null)
|
const islandRef = ref<null | typeof NuxtIsland>(null)
|
||||||
|
|
||||||
expose({
|
expose({
|
||||||
@ -21,7 +22,10 @@ export const createServerComponent = (name: string) => {
|
|||||||
name,
|
name,
|
||||||
lazy: props.lazy,
|
lazy: props.lazy,
|
||||||
props: attrs,
|
props: attrs,
|
||||||
ref: islandRef
|
ref: islandRef,
|
||||||
|
onError: (err) => {
|
||||||
|
emit('error', err)
|
||||||
|
}
|
||||||
}, slots)
|
}, slots)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -111,11 +111,32 @@ describe('runtime server component', () => {
|
|||||||
expect(component.html()).toBe('<div>2</div>')
|
expect(component.html()).toBe('<div>2</div>')
|
||||||
vi.mocked(fetch).mockReset()
|
vi.mocked(fetch).mockReset()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('expect NuxtIsland to emit an error', async () => {
|
||||||
|
const stubFetch = vi.fn(() => {
|
||||||
|
throw new Error('fetch error')
|
||||||
|
})
|
||||||
|
|
||||||
|
vi.stubGlobal('fetch', stubFetch)
|
||||||
|
|
||||||
|
const wrapper = await mountSuspended(createServerComponent('ErrorServerComponent'), {
|
||||||
|
props: {
|
||||||
|
name: 'Error',
|
||||||
|
props: {
|
||||||
|
force: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attachTo: 'body'
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(fetch).toHaveBeenCalledOnce()
|
||||||
|
expect(wrapper.emitted('error')).toHaveLength(1)
|
||||||
|
vi.mocked(fetch).mockReset()
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
describe('client components', () => {
|
describe('client components', () => {
|
||||||
|
|
||||||
it('expect swapping nuxt-client should not trigger errors #25289', async () => {
|
it('expect swapping nuxt-client should not trigger errors #25289', async () => {
|
||||||
const mockPath = '/nuxt-client.js'
|
const mockPath = '/nuxt-client.js'
|
||||||
const componentId = 'Client-12345'
|
const componentId = 'Client-12345'
|
||||||
@ -166,7 +187,7 @@ describe('client components', () => {
|
|||||||
expect(fetch).toHaveBeenCalledOnce()
|
expect(fetch).toHaveBeenCalledOnce()
|
||||||
|
|
||||||
expect(wrapper.html()).toMatchInlineSnapshot(`
|
expect(wrapper.html()).toMatchInlineSnapshot(`
|
||||||
"<div data-island-uid="3">hello<div data-island-uid="3" data-island-component="Client-12345">
|
"<div data-island-uid="4">hello<div data-island-uid="4" data-island-component="Client-12345">
|
||||||
<div>client component</div>
|
<div>client component</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -192,7 +213,7 @@ describe('client components', () => {
|
|||||||
await wrapper.vm.$.exposed!.refresh()
|
await wrapper.vm.$.exposed!.refresh()
|
||||||
await nextTick()
|
await nextTick()
|
||||||
expect(wrapper.html()).toMatchInlineSnapshot(`
|
expect(wrapper.html()).toMatchInlineSnapshot(`
|
||||||
"<div data-island-uid="3">hello<div>
|
"<div data-island-uid="4">hello<div>
|
||||||
<div>fallback</div>
|
<div>fallback</div>
|
||||||
</div>
|
</div>
|
||||||
</div>"
|
</div>"
|
||||||
@ -202,7 +223,6 @@ describe('client components', () => {
|
|||||||
expectNoConsoleIssue()
|
expectNoConsoleIssue()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
it('should not replace nested client components data-island-uid', async () => {
|
it('should not replace nested client components data-island-uid', async () => {
|
||||||
const componentId = 'Client-12345'
|
const componentId = 'Client-12345'
|
||||||
|
|
||||||
@ -286,7 +306,7 @@ describe('client components', () => {
|
|||||||
})
|
})
|
||||||
expect(fetch).toHaveBeenCalledOnce()
|
expect(fetch).toHaveBeenCalledOnce()
|
||||||
expect(wrapper.html()).toMatchInlineSnapshot(`
|
expect(wrapper.html()).toMatchInlineSnapshot(`
|
||||||
"<div data-island-uid="5">hello<div data-island-uid="5" data-island-component="ClientWithSlot-12345">
|
"<div data-island-uid="6">hello<div data-island-uid="6" data-island-component="ClientWithSlot-12345">
|
||||||
<div class="client-component">
|
<div class="client-component">
|
||||||
<div style="display: contents" data-island-uid="" data-island-slot="default">
|
<div style="display: contents" data-island-uid="" data-island-slot="default">
|
||||||
<div>slot in client component</div>
|
<div>slot in client component</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user